Solidity Emission Models
An emission model is a rule for creating new tokens at a fixed rate over time. A cap is the largest total the model will ever create.
A warped interval mints rate times elapsed time
Minting multiplies the elapsed seconds by the fixed rate. Minting twice at the same time creates nothing the second time.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
contract Emitter {
uint256 public rate;
uint256 public totalMinted;
uint256 public lastTime;
constructor() {
rate = 10;
lastTime = block.timestamp;
}
function mint() public returns (uint256 amount) {
uint256 elapsed = block.timestamp - lastTime;
amount = elapsed * rate;
totalMinted += amount;
lastTime = block.timestamp;
}
}
Minting stops exactly at the cap
A mint that would pass the cap is trimmed to the remaining room. Later mints create nothing once the cap is reached.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
contract CappedEmitter {
uint256 public rate;
uint256 public cap;
uint256 public totalMinted;
uint256 public lastTime;
constructor() {
rate = 10;
cap = 5000;
lastTime = block.timestamp;
}
function mint() public returns (uint256 amount) {
uint256 elapsed = block.timestamp - lastTime;
amount = elapsed * rate;
if (totalMinted + amount > cap) {
amount = cap - totalMinted;
}
totalMinted += amount;
lastTime = block.timestamp;
}
}
Two intervals add up to the full minted total
Each mint updates the last mint time before the next interval starts. The two interval amounts sum to the running total.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
contract SteadyEmitter {
uint256 public rate;
uint256 public totalMinted;
uint256 public lastTime;
constructor() {
rate = 10;
lastTime = block.timestamp;
}
function mint() public returns (uint256 amount) {
uint256 elapsed = block.timestamp - lastTime;
amount = elapsed * rate;
totalMinted += amount;
lastTime = block.timestamp;
}
}
Example
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
contract EmissionToken {
uint256 public rate;
uint256 public cap;
uint256 public totalMinted;
uint256 public lastTime;
mapping(address => uint256) public balances;
constructor() {
rate = 10;
cap = 5000;
lastTime = block.timestamp;
}
function mintTo(address to) public returns (uint256 amount) {
uint256 elapsed = block.timestamp - lastTime;
amount = elapsed * rate;
if (totalMinted + amount > cap) {
amount = cap - totalMinted;
}
totalMinted += amount;
balances[to] += amount;
lastTime = block.timestamp;
}
}
Key points
- Emission: Emission is the creation of new tokens on a set schedule.
- Rate: A rate is the number of new tokens created per second.
- Interval: An interval is the time between two mints and it decides how many tokens the mint creates.
- Cap: A cap is the maximum total supply an emission model will create.
- Restatement: Emissions add supply steadily over time until the cap stops further creation.
In this example, EmissionToken mints to a holder over a first interval, mints the remaining room up to the cap over a long second interval, and then mints nothing further.
Note
The rate in this toy contract is fixed and a real model may change its rate by a separate rule.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Remix IDE
Exercise
A model mints 10 tokens per second with a cap of 5000. How many tokens does a 100-second interval mint?