Skip to main content

Overview

GatePass contracts are deployed on Polygon using Foundry, a fast and modern Ethereum development toolkit. This guide covers deploying the factory contract and creating your first event.
Make sure you have MATIC tokens in your wallet for gas fees. Even though Polygon is cheap, you’ll need ~$1-2 worth of MATIC for deployment.

Prerequisites

1

Install Foundry

Install Foundry (Forge, Cast, Anvil) for Solidity development
curl -L https://foundry.paradigm.xyz | bash
foundryup
2

Clone Repository

Clone the GatePass contracts repository
git clone https://github.com/yourorg/gatepass-contracts
cd gatepass-contracts/src/packages/contracts
3

Install Dependencies

Install OpenZeppelin and other dependencies
forge install
4

Configure Environment

Create a .env file with your deployment credentials
cp .env.example .env
# Edit .env with your private key and RPC URL

Environment Configuration

Create a .env file in the contracts directory:
.env
# Deployer wallet private key (without 0x prefix)
PRIVATE_KEY=your_private_key_here

# Platform fee recipient address
PLATFORM_FEE_RECIPIENT=0xYourPlatformFeeAddress

# Network configuration
NETWORK_NAME=polygon
RPC_URL=https://polygon-rpc.com

# Polygonscan API key for verification
POLYGONSCAN_API_KEY=your_api_key_here
Never commit your .env file to version control! Add it to .gitignore immediately.

Deployment Script

The deployment script (script/Deploy.s.sol) handles:
  1. Deploying the EventTicketFactory contract
  2. Deploying the EventTicket implementation contract
  3. Setting the platform fee recipient
  4. Saving deployment information to a JSON file
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import "forge-std/Script.sol";
import "../src/EventTicketFactory.sol";

contract Deploy is Script {
    function run() external {
        uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
        address platformFeeRecipient = vm.envAddress("PLATFORM_FEE_RECIPIENT");

        vm.startBroadcast(deployerPrivateKey);

        // Deploy the factory contract
        EventTicketFactory factory = new EventTicketFactory(platformFeeRecipient);

        console.log("EventTicketFactory deployed to:", address(factory));
        console.log("Implementation contract:", factory.getImplementation());
        console.log("Platform fee recipient:", factory.platformFeeRecipient());
        console.log("Platform fee (bps):", factory.platformFeeBps());

        vm.stopBroadcast();

        // Write deployment info to file
        string memory deploymentInfo = string(
            abi.encodePacked(
                "{\n",
                '  "factory": "', vm.toString(address(factory)), '",\n',
                '  "implementation": "', vm.toString(factory.getImplementation()), '",\n',
                '  "platformFeeRecipient": "', vm.toString(platformFeeRecipient), '",\n',
                '  "platformFeeBps": ', vm.toString(factory.platformFeeBps()), ',\n',
                '  "network": "', vm.envString("NETWORK_NAME"), '",\n',
                '  "deployedAt": ', vm.toString(block.timestamp), '\n',
                "}"
            )
        );

        vm.writeFile("./deployments/latest.json", deploymentInfo);
        console.log("Deployment info saved to ./deployments/latest.json");
    }
}

Step-by-Step Deployment

1. Deploy Factory Contract

# Load environment variables
source .env

# Deploy to Polygon
forge script script/Deploy.s.sol:Deploy \
  --rpc-url https://polygon-rpc.com \
  --broadcast \
  --verify \
  --etherscan-api-key $POLYGONSCAN_API_KEY \
  -vvvv
[⠊] Compiling...
[⠃] Compiling 25 files with 0.8.24
[⠊] Solc 0.8.24 finished in 3.45s
Compiler run successful

## Setting up 1 EVM.
==========================

Chain 137

Estimated gas price: 30.000000001 gwei
Estimated total gas used for script: 2134567
Estimated amount required: 0.064037010002134567 MATIC

##### polygon
✅  [Success] Hash: 0x1234...5678
Contract Address: 0xFactoryAddress...
Block: 12345678
Paid: 0.062 MATIC

EventTicketFactory deployed to: 0xFactoryAddress...
Implementation contract: 0xImplementationAddress...
Platform fee recipient: 0xYourPlatformFeeAddress
Platform fee (bps): 250

✅ Sequence #1 on polygon | Total Paid: 0.062 MATIC

2. Verify Deployment

After deployment, verify the contracts on Polygonscan:
forge verify-contract \
  --chain-id 137 \
  --num-of-optimizations 200 \
  --watch \
  --constructor-args $(cast abi-encode "constructor(address)" $PLATFORM_FEE_RECIPIENT) \
  --etherscan-api-key $POLYGONSCAN_API_KEY \
  --compiler-version v0.8.24+commit.e11b9ed9 \
  $FACTORY_ADDRESS \
  src/EventTicketFactory.sol:EventTicketFactory

3. Save Deployment Info

The script automatically saves deployment information to deployments/latest.json:
deployments/latest.json
{
  "factory": "0xFactoryAddress...",
  "implementation": "0xImplementationAddress...",
  "platformFeeRecipient": "0xYourPlatformFeeAddress",
  "platformFeeBps": 250,
  "network": "polygon",
  "deployedAt": 1710345600
}

Creating Your First Event

After deploying the factory, you can create events using the createEvent function.

Using the Deployment Script

# Set factory address in .env
echo "FACTORY_ADDRESS=0xYourFactoryAddress" >> .env

# Run create event script
forge script script/Deploy.s.sol:CreateTestEvent \
  --rpc-url $RPC_URL \
  --broadcast \
  -vvvv

Using Cast CLI

cast send $FACTORY_ADDRESS \
  "createEvent(string,string,uint256,uint256,uint256,uint256,uint256,string)" \
  "My Concert" \
  "CONCERT" \
  1000 \
  "10000000000000000" \
  $(date +%s) \
  $(($(date +%s) + 604800)) \
  $(($(date +%s) + 1209600)) \
  "https://api.myevent.com/metadata/" \
  --rpc-url $RPC_URL \
  --private-key $PRIVATE_KEY

Parameters Explained

eventName
string
required
Name of the event (e.g., “DevCon 2024”)
eventSymbol
string
required
Symbol for the NFT tickets (e.g., “DEVCON24”)
totalSupply
uint256
required
Maximum number of tickets available (1-10000)
ticketPrice
uint256
required
Price per ticket in wei (e.g., 0.01 ether = “10000000000000000”)
saleStart
uint256
required
Unix timestamp when ticket sales begin
saleEnd
uint256
required
Unix timestamp when ticket sales end (must be before eventDate)
eventDate
uint256
required
Unix timestamp of the actual event
baseTokenURI
string
required
Base URI for token metadata (e.g., “https://api.example.com/metadata/“)

Example Script

const { ethers } = require('ethers');

async function createEvent() {
  const provider = new ethers.JsonRpcProvider('https://polygon-rpc.com');
  const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider);
  
  const factoryABI = ['function createEvent(string,string,uint256,uint256,uint256,uint256,uint256,string) returns (address)'];
  const factory = new ethers.Contract(factoryAddress, factoryABI, wallet);
  
  const now = Math.floor(Date.now() / 1000);
  const tx = await factory.createEvent(
    'DevCon 2024',
    'DEVCON24',
    1000, // 1000 tickets
    ethers.parseEther('0.01'), // 0.01 MATIC per ticket
    now, // Sale starts now
    now + (7 * 24 * 60 * 60), // Sale ends in 7 days
    now + (14 * 24 * 60 * 60), // Event in 14 days
    'https://api.example.com/metadata/'
  );
  
  const receipt = await tx.wait();
  console.log('Event created:', receipt);
}

createEvent();

Testing Deployment

Before deploying to mainnet, test on a local fork or testnet:

Local Testing with Anvil

# Start local Polygon fork
anvil --fork-url https://polygon-rpc.com

# Deploy to local fork
forge script script/Deploy.s.sol:Deploy \
  --rpc-url http://127.0.0.1:8545 \
  --broadcast

Run Tests

# Run all tests
forge test

# Run tests with verbosity
forge test -vvv

# Run specific test
forge test --match-test testMintTicket

# Run tests with gas reporting
forge test --gas-report

Post-Deployment

1

Update Frontend

Update your frontend configuration with the deployed factory address
2

Configure Platform Fee

Adjust platform fee if needed (default is 2.5%)
cast send $FACTORY_ADDRESS \
  "setPlatformFee(uint256)" \
  200 \
  --rpc-url $RPC_URL \
  --private-key $PRIVATE_KEY
3

Monitor Events

Set up event monitoring for EventContractDeployed events
4

Document Addresses

Save all contract addresses in your documentation and configuration

Troubleshooting

Make sure your deployer wallet has enough MATIC. You need ~$2-3 worth for deployment.
# Check balance
cast balance $DEPLOYER_ADDRESS --rpc-url $RPC_URL
Your transaction nonce is outdated. Wait for pending transactions to confirm.
# Check pending transactions
cast nonce $DEPLOYER_ADDRESS --rpc-url $RPC_URL
If contract verification fails, manually verify on Polygonscan:
  1. Go to Polygonscan
  2. Find your contract
  3. Click “Verify and Publish”
  4. Select “Solidity (Standard Json-Input)”
  5. Upload the standard JSON input from forge verify-contract

Next Steps

EventTicket Contract

Learn about the EventTicket contract functionality

Factory Contract

Detailed factory contract documentation

Build docs developers (and LLMs) love