Server-side Solidity Compilation API

if you've compiled a Solidity contract, you know the easiest way to do it is with a JavaScript library like Ethers, Hardhat, Web3, etc.

but what if you need to compile a contract server-side, for later interactions client-side? we needed exactly this solution for Mint Site -- our free, no-code solution that creates + deploys a smart contract and generates an NFT minting page -- so we built it.

Mint Server

first, NFT creators simply click "Deploy to Heroku" from our GitHub repo:

https://github.com/oojuteam/mint_site

after logging into their deployed instance they're able to configure their NFT project in seconds, setting the blockchain network (Polygon, Eth, Klaytn, etc) as well as the token pricing, project name, and so on.

once these settings are saved, their contract is ready to be compiled.

Contract Compilation

we initially intended to include the compilation feature on this free codebase, however 2 challenges immediately arose:

1. given our users are not technical and are deploying to a free Heroku server, it's non-trivial to include the buildpacks necessary to run system binaries that enable Solidity compilation

2. the other leg of our service, "verifying" the contract once it's deployed (for access via scanner web3 UIs) would require exposing sensitive API credentials on this open source repository

to mitigate these challenges we built a 2nd server with a couple endpoints -- compile and verify.

here's how it works.

Base URI

# POST https://compile.ooju.xyz/contract_compilations

Body params

{
  purchase_price: 1000000000000000000, // amount in wei/gwei
  mint_qty_max: 10, // max # of assets that can be purchased in 1 transaction
  creator_wallet_address: 0x00000, // wallet address of the creator; 100% of funds are withdrawable here
  name: "MyProject", // becomes the smart contract name
  symbol: "MYPROJ" // project's token symbol
}

Response params

our compilation server has a flattened contract template with common features like mint(), giveaway(), startSale(), stopSale(), withdraw(), and so on, allowing creators the flexibility to manage their NFT over time.

when the payload described above hits this endpoint, our contract template essentially gets a "find and replace" treatment, swapping out necessary variables to customize it for the user.

{ 
  abi: [{"inputs":[],"stateMutability":"nonpayable","type":"constructor"}, ...], 
  bytes: "0x6080604052348015620000115....", 
  source: "// SPDX-License-Identifier: MIT \npragma solidity ^0.8.2; ..."
}

this response includes the compiled contract's ABI, bytecode, and source code.

the "ABI" and "bytes" params are used by our Mint Site's frontend, which prompts them via Metamask to deploy the contract and pay gas fees. the "source" param is useful for contract verification via the Polygonscan API, in the case that a user deploys their contract to Polygon.

Example Compilation

if you're familiar with cURL, paste the following request into your terminal to see how it works:

curl -XPOST 'https://compile.ooju.xyz/contract_compilations' \
-d 'purchase_price=1000000000000000000&mint_qty_max=10&creator_wallet_address=0x9880828B2188907Ea2448F5d20f9B28066076474&name=OojuMintContract&symbol=OOJU'

in return you'll receive the 3 parameters described above.

Verifying Contracts

once a contract is deployed to Polygon, Ethereum, or one of their testnets, it needs to be verified for the scanners' web3 interfaces to be usable. since this step of the contract deployment is gas-free, we simply built another endpoint.

# POST https://compile.ooju.xyz/contract_verifications

the body of this request requires the previously deployed smart contract's address, source code, name, and network.

{
  address: "0x....", // contract address
  source_code: "// SPDX-License-Identifier: MIT\n pragma solidity ^0.8.2;",
  name: "OojuMint",
  network: "matic" // matic = Polygon, maticmum = Mumbai, etc (using official Ethers js labels)
}

given the 30-60 second wait time for a contract to be verified, the scanners (Polygonscan.com, Etherscan.io) provide a GUID, which we then return to our Mint Site server.

{ status: "ok", result: "guid-goes-here" }

lastly, our Mint Site server begins polling our 3rd and final endpoint:

# POST https://compile.ooju.xyz/contract_verifications?check=true

this is the same endpoint as the verification itself, but with a "check" parameter that tells our server to look for a "guid" parameter in the body params.

{
  guid: "verified-contract-guid-here"
}

the compile server responds with a simple true/false.

{ verified: true }

Next Steps

we'd love to extend the "compile" endpoint to consume contract source code (vs relying on our template), as well as expanding the "verify" endpoint to support a user's own scanner API key.

other ideas include new parameters for setting the Solidity compiler version (currently hardcoded to 0.8.3), optimization runs, as well as constructor arguments.

if you'd like to use or hack on this API in your own projects, reach out to us at [email protected].