The CDP SDK supports deploying custom contracts alongside ERC-20s (fungible tokens), ERC-721s (NFTs), and ERC-1155s (MultiTokens). If you’d like to see support for additional contracts, contact us in the CDP Discord.

  • Agent-generated Contracts: Allow your agents to independently create and programmatically deploy smart contracts, enabling features like:
    • Escrow contracts
    • Single-use contracts for complex DeFi operations
    • Hyper-personalized apps
  • Expansive Gaming Ecosystem: Create autonomous in-game currencies and items.
  • NFT-based Verification for Photos: Create a camera app that mints an NFT upon photo capture to prove its provenance.
  • Loyalty Programs: Introduce a loyalty program for your users that can be used across your platform and on others.
  • AI-Generated Game Assets: Use fungible and non-fungible tokens alongside artificial intelligence to allow users to build their own characters and assets.

Examples

See supported methods at the bottom of this page for a list of all the methods supported by each contract type.

Deploying an Arbitrary Contract

To deploy an arbitrary contract, first write a Solidity smart contract, then get the contract in the input JSON format. There are three ways to do this:

  1. Remix (web-based, recommended): Use the web-based Remix IDE to compile your Solidity contract (Ctrl + S within the .sol file), then in the file explorer navigate to the ‘build-info’ folder to find your Solidity input JSON format. Grab the first portion of the JSON file, going from line 1 to the end bracket before the “output” property.
  2. Foundry (best for complex, production-ready contracts): In traditional smart contract development, toolchains like Foundry are great for production-ready testing and development. Foundry has a command to build and compile contracts in the JSON format:
forge build --print-compiler-input > compiler_input.json
  1. AI-generated input JSON (simplest contracts): Have AI generate Solidity code in the input JSON format; AgentKit agents are prompted with some additional context on how to build them, and is generally accurate on simple smart contracts. Due to limitations with current models, AI may not be able to generate complex multi-file architectures.

Next, execute the following command to compile and deploy the contract:

    const smartContract: SmartContract = await wallet.deployContract({ 
        solidityVersion: '0.8.28+commit.7893614a', // acceptable versions can be found at https://binaries.soliditylang.org/bin/list.json
        solidityInputJson: contractInputJson,
        contractName: "SomeContractName",
        constructorArgs: {
          param: "someValue",
          param2: "someOtherValue",
        }
    });
    await smartContract.wait()

The contract code will be automatically verified and available for viewing on Etherscan’s family of blockchain explorers.

Deploying an ERC-20

ERC-20 tokens are the most common type of fungible token on Ethereum. Interacting with the contract is done through the Transfer API for simple transfers, or with the invokeContract function for other calls. All standard ERC-20 functions are supported. Below is an example of how to call a deployed ERC20 contract.

Tokens can be created and interacted with by doing the following:

    import { SmartContract } from "@coinbase/coinbase-sdk"

    // Create a new wallet (or import an existing one)
    const wallet = await Wallet.create();

    // Fund the wallet manually or use the [base-sepolia faucet](./wallets.mdx#faucets)

    // Deploy the token
    const deployedContract: SmartContract = await wallet.deployToken({
        name: "ExampleCoin",
        symbol: "EXAM",
        totalSupply: 100000
    });
    await deployedContract.wait();
    
    // Interact with the deployed contract
    const approveArgs = {
        spender: "0xApprovedSpender",
        value: "10000000",
    };

    const contractInvocation = await wallet.invokeContract({
        contractAddress: deployedContract.getContractAddress(),
        method: "approve",
        args: approveArgs,
    });
    await contractInvocation.wait();

Deploying an ERC-721

ERC-721 is the standard for non-fungible tokens on Ethereum. The URI is the location of the metadata for the NFT. To properly interact with marketplaces, the URI must be a valid JSON file.

The creation and interaction process is similar to fungible tokens:

    const nft = await wallet.deployNFT({
        name: "My NFT",
        symbol: "MNFT",
        baseURI: "https://my-nft-base-uri.com/metadata/",
    });
    await nft.wait();

    // Mint 3 token to destinationAddress by calling invokeContract
    const mintTx = await wallet.invokeContract({
        contractAddress: nft.getContractAddress(),
        method: "mint",
        args: {
            to: "0xDestinationAddress",
            quantity: "3",
        },
    });
    await mintTx.wait();

Deploying an ERC-1155

ERC-1155 is the standard for multi-token fungible tokens on Ethereum. Instead of minting one token at a time, you can mint multiple tokens in a single transaction with the same metadata. This guide explains how to define the metadata properly.

Two mint methods are supported: mint and mintBatch. mint requires a single to address and mintBatch requires an array of to addresses and an array of values of the same length.

    const multiToken = await wallet.deployMultiToken({
      uri: "https://example.com/{id}.json",
    });
    await multiToken.wait();

    const multiTokenAddress = multiToken.getContractAddress();

    // Mint 1 token to destinationAddress by calling invokeContract
    const mintTx = await addr.invokeContract({
      contractAddress: multiTokenAddress,
      method: "mint",
      args: {
        to: "0xDestinationAddress",
        id: "1",
        value: "1",
      },
    });
    await mintTx.wait();
    
    // let's do a mintBatch
    const mintBatchTx = await addr.invokeContract({
      contractAddress: multiTokenAddress,
      method: "mintBatch",
      args: {
        to: "0xDestinationAddress",
        ids: ["1", "2"],
        values: ["5", "10"],
      },
    });
    await mintBatchTx.wait();

Supported Methods

ERC-20 Functions

Inherits: ERC20

constructor

Constructor to initialize the ERC20 token with a name, symbol, and initial supply. The entire initial supply is assigned to the deployer of the contract.

constructor(string memory name, string memory symbol, uint256 amount) ERC20(name, symbol);

ERC-721 Functions

Inherits: ERC721AQueryable, Ownable2Step

constructor

Constructor to initialize the token with name, symbol, base URI, and deployer address

constructor(string memory name, string memory symbol, string memory baseURI)
    ERC721A(name, symbol)
    Ownable(msg.sender);

Parameters

NameTypeDescription
namestringThe name of the token
symbolstringThe symbol of the token
baseURIstringThe base URI for the token metadata

mint

Mint a single token to a specified address

Only the contract owner can call this function

function mint(address to) external onlyOwner;

Parameters

NameTypeDescription
toaddressThe address to mint the token to

mint

Mint a single token to a specified address with data

Only the contract owner can call this function

function mint(address to, bytes memory data) external onlyOwner;

Parameters

NameTypeDescription
toaddressThe address to mint the token to
databytesThe data to pass to the minted token

mint

Mint a specified quantity of tokens to a specified address

Only the contract owner can call this function

function mint(address to, uint8 quantity) external onlyOwner;

Parameters

NameTypeDescription
toaddressThe address to mint tokens to
quantityuint8The number of tokens to mint

mint

Mint a specified quantity of tokens to a specified address with data

Only the contract owner can call this function

function mint(address to, uint8 quantity, bytes memory data) external onlyOwner;

Parameters

NameTypeDescription
toaddressThe address to mint tokens to
quantityuint8The number of tokens to mint
databytesThe data to pass to the minted tokens

ERC-1155 Functions

Inherits: ERC1155Supply, Ownable2Step

constructor

Constructs an ERC1155 token with a URI, owned by the deployer of the contract

constructor(string memory uri) ERC1155(uri) Ownable(msg.sender);

Parameters

NameTypeDescription
uristringThe URI for all the token metadata, should be of the format “https://token-cdn-domain/{id}.json

mint

Mint a new token which can be fungible or non-fungible. Non-fungible tokens have a unique ID with a total supply of 1

function mint(address to, uint256 id, uint256 value) external onlyOwner;

Parameters

NameTypeDescription
toaddressThe address to receive the minted tokens
iduint256The ID of the token to mint
valueuint256The amount of tokens to mint

mint

Mint a new token which can be fungible or non-fungible. Non-fungible tokens have a unique ID with a total supply of 1

function mint(address to, uint256 id, uint256 value, bytes memory data) external onlyOwner;

Parameters

NameTypeDescription
toaddressThe address to receive the minted tokens
iduint256The ID of the token to mint
valueuint256The amount of tokens to mint
databytesAdditional data with no specified format, to be passed to the receiver contract

mintBatch

Mint a batch of new tokens which can be fungible or non-fungible. Non-fungible tokens have a unique ID with a total supply of 1

function mintBatch(address to, uint256[] memory ids, uint256[] memory values) external onlyOwner;

Parameters

NameTypeDescription
toaddressThe address to receive the minted tokens
idsuint256[]The IDs of the tokens to mint
valuesuint256[]The amounts of tokens to mint, must be the same length as ids

mintBatch

Mint a batch of new tokens which can be fungible or non-fungible. Non-fungible tokens have a unique ID with a total supply of 1

function mintBatch(address to, uint256[] memory ids, uint256[] memory values, bytes memory data) external onlyOwner;

Parameters

NameTypeDescription
toaddressThe address to receive the minted tokens
idsuint256[]The IDs of the tokens to mint
valuesuint256[]The amounts of tokens to mint, must be the same length as ids
databytesAdditional data with no specified format, to be passed to the receiver contract