Ethereum Settlers
1. Overview
An ERC20 token called Ethereum Settler
(SETTLER) and an ERC721 NFT token called Ethereum Settlement
(SETTLEMENT).
Minting a Settlement NFT is free and can be done by anyone. The only cost is the gas fee for the transaction.
Holding a Settlement NFT gives the holder a newly minted SETTLER tokens every second.
Invariant: A Settlement NFT can only be held by one address at a time.
There is nothing stopping multiple addresses from each holding different Settlement NFTs. E.g. Mint ➜ Send ➜ Mint ➜ Send, etc. This means that the SETTLER token can have no monetary value, as it is not a scarce resource and an unlimited amount can be created simply by minting more Settlement NFTs.
The ViewAggregator contract is used to perform batch queries on the Settlement contract to get sequential or random data. This is a view only helper contract that is deployed separately from the Settlement contract.
Live on https://settlers.eridian.xyz
2. Clone repository
git clone https://github.com/EridianAlpha/ethereum-settlers.git
2.1. Install Dependencies
This should happen automatically when first running a command, but the installation can be manually triggered with the following commands:
git submodule init
git submodule update
make install
2.2. Create the .env
file
Use the .env.example
file as a template to create a .env
file.
3. Testing
3.1. Tests
make test
make test-fork
make test-v
make test-v-fork
make test-summary
make test-summary-fork
3.2. Coverage
make coverage
make coverage-fork
make coverage-report
make coverage-report-fork
4. Deployment
4.1. Deploy NFT and Token Contract
Deploy the SettlementNft contract which deploys the SettlerTokens contract.
Chain | Command |
---|---|
Anvil | make deploy anvil |
Holesky | make deploy holesky |
Mainnet | make deploy mainnet |
Base Sepolia | make deploy base-sepolia |
Base Mainnet | make deploy base-mainnet |
4.2. Deploy View Aggregator Contract
Deploy the ViewAggregator contract.
Input value as a the Settlement contract deployment address e.g. 0x123...
.
Chain | Command |
---|---|
Anvil | make deployViewAggregator anvil |
Holesky | make deployViewAggregator holesky |
Mainnet | make deployViewAggregator mainnet |
Base Sepolia | make deployViewAggregator base-sepolia |
Base Mainnet | make deployViewAggregator base-mainnet |
5. Interactions
Interactions are defined in ./script/Interactions.s.sol
5.1. Mint Settlement NFT
Call the mint()
function on the SettlementNft contract.
Chain | Command |
---|---|
Anvil | make mintNft anvil |
Holesky | make mintNft holesky |
Mainnet | make mintNft mainnet |
Base Sepolia | make mintNft base-sepolia |
Base Mainnet | make mintNft base-mainnet |
5.2. Get NFT Mint Timestamp
Call the getMintTimestamp()
function on the SettlementNft contract.
Input value as a token ID e.g. 1
.
Chain | Command |
---|---|
Anvil | make getMintTimestamp anvil |
Holesky | make getMintTimestamp holesky |
Mainnet | make getMintTimestamp mainnet |
Base Sepolia | make getMintTimestamp base-sepolia |
Base Mainnet | make getMintTimestamp base-mainnet |
5.3. Get Settler Balance
Call the getSettlerBalance()
function on the SettlementNft contract.
Input value as an address e.g. 0x123...
.
Chain | Command |
---|---|
Anvil | make getSettlerBalance anvil |
Holesky | make getSettlerBalance holesky |
Mainnet | make getSettlerBalance mainnet |
Base Sepolia | make getSettlerBalance base-sepolia |
Base Mainnet | make getSettlerBalance base-mainnet |
5.4. Get Sequential Data
Call the getSequentialData()
function on the ViewAggregator contract.
Input value 1 as the starting token ID e.g. 1
.
Input value 2 as the ending token ID e.g. 10
.
Chain | Command |
---|---|
Anvil | make getSequentialData anvil |
Holesky | make getSequentialData holesky |
Mainnet | make getSequentialData mainnet |
Base Sepolia | make getSequentialData base-sepolia |
Base Mainnet | make getSequentialData base-mainnet |
5.5. Get Random Data
Call the getRandomData()
function on the ViewAggregator contract.
Input value as a number of NFTs to return e.g. 20
.
Chain | Command |
---|---|
Anvil | make getRandomData anvil |
Holesky | make getRandomData holesky |
Mainnet | make getRandomData mainnet |
Base Sepolia | make getRandomData base-sepolia |
Base Mainnet | make getRandomData base-mainnet |
6. License
SettlementNft
Inherits: ERC721
Author: EridianAlpha
An ERC721 NFT token called Ethereum Settlement
(SETTLEMENT).
State Variables
BASE_IMAGE_URI
string public BASE_IMAGE_URI;
SETTLER_TOKEN
SettlerToken public immutable SETTLER_TOKEN;
nextTokenId
uint256 public nextTokenId = 1;
s_mintTimestamp
mapping(uint256 => uint256) internal s_mintTimestamp;
s_ownerToId
mapping(address => uint256) internal s_ownerToId;
Functions
constructor
Constructor to initialize the contract with a base image URI and deploy the SettlerToken contract.
constructor(string memory _baseImageUri) ERC721("Ethereum Settlement", "SETTLEMENT");
Parameters
Name | Type | Description |
---|---|---|
_baseImageUri | string | The base URI for the NFT image. |
_update
Override standard ERC721 _update
function.
Mints outstanding SETTLER tokens. Checks only 1 NFT per address.
function _update(address to, uint256 tokenId, address auth) internal override returns (address previousOwner);
Parameters
Name | Type | Description |
---|---|---|
to | address | The address to transfer the NFT to. |
tokenId | uint256 | The ID of the NFT. |
auth | address | The address that is authorized to transfer the NFT. |
Returns
Name | Type | Description |
---|---|---|
previousOwner | address | The previous owner of the NFT. |
mint
Override standard ERC721 mint
function.
Mints a new NFT and sets the mint timestamp. Adds the msg.sender to the s_ownerToId mapping.
function mint() external;
tokenURI
Override standard ERC721 tokenURI
function.
Generates the JSON metadata for the NFT.
function tokenURI(uint256 tokenId) public view override returns (string memory uri);
Parameters
Name | Type | Description |
---|---|---|
tokenId | uint256 | The ID of the NFT. |
Returns
Name | Type | Description |
---|---|---|
uri | string | The JSON metadata for the NFT. |
_generateAttributes
Generates the attributes for the NFT used in the tokenURI.
function _generateAttributes(uint256 tokenId) internal view returns (string memory attributes);
Parameters
Name | Type | Description |
---|---|---|
tokenId | uint256 | The ID of the NFT. |
Returns
Name | Type | Description |
---|---|---|
attributes | string | The attributes for the NFT. |
_generateSvg
Generates the SVG for the NFT.
function _generateSvg(uint256 tokenId) internal view returns (string memory svg);
Parameters
Name | Type | Description |
---|---|---|
tokenId | uint256 | The ID of the NFT. |
Returns
Name | Type | Description |
---|---|---|
svg | string | The SVG for the NFT. |
_generateSettlementRectangle
Generates the SVG rectangle for the settlement ID.
function _generateSettlementRectangle(string memory tokenIdString) internal pure returns (string memory rectangleSvg);
Parameters
Name | Type | Description |
---|---|---|
tokenIdString | string | The ID of the NFT as a string. |
Returns
Name | Type | Description |
---|---|---|
rectangleSvg | string | The SVG rectangle for the settlement ID. |
_generateDaysSinceMintRectangle
Generates the SVG rectangle for the days since mint.
function _generateDaysSinceMintRectangle(uint256 tokenId) internal view returns (string memory rectangleSvg);
Parameters
Name | Type | Description |
---|---|---|
tokenId | uint256 | The ID of the NFT. |
Returns
Name | Type | Description |
---|---|---|
rectangleSvg | string | The SVG rectangle for the days since mint. |
_daysSinceMint
Calculates the days since mint for an NFT.
function _daysSinceMint(uint256 _mintTimestamp) internal view returns (uint256 daysSinceMint);
Parameters
Name | Type | Description |
---|---|---|
_mintTimestamp | uint256 | The timestamp when the NFT was minted. |
Returns
Name | Type | Description |
---|---|---|
daysSinceMint | uint256 | The days since the NFT was minted. |
getOwnerToId
Getter function to get the NFT ID from an owner address.
function getOwnerToId(address owner) external view returns (uint256 tokenId);
Parameters
Name | Type | Description |
---|---|---|
owner | address | The address of the NFT owner. |
Returns
Name | Type | Description |
---|---|---|
tokenId | uint256 | The ID of the NFT. |
getMintTimestamp
Getter function to get the mint timestamp of an NFT from a token ID.
function getMintTimestamp(uint256 tokenId) external view returns (uint256 mintTimestamp);
Parameters
Name | Type | Description |
---|---|---|
tokenId | uint256 | The ID of the NFT. |
Returns
Name | Type | Description |
---|---|---|
mintTimestamp | uint256 | The timestamp when the NFT was minted. |
Errors
SettlementNft_SingleActivePerAddress
error SettlementNft_SingleActivePerAddress();
SettlerToken
Inherits: ERC20, ERC20Permit
Author: EridianAlpha
An ERC20 token called Ethereum Settler
(SETTLER).
State Variables
TOKEN_EMISSION_RATE
uint256 public constant TOKEN_EMISSION_RATE = 1e18;
SETTLEMENT_NFT
SettlementNft public immutable SETTLEMENT_NFT;
s_mintedTokensFromNft
mapping(uint256 => uint256) public s_mintedTokensFromNft;
Functions
constructor
Constructor for the Settler Token contract to initialize the Settlement NFT address.
constructor(address _nftAddress) ERC20("Ethereum Settler", "SETTLER") ERC20Permit("Ethereum Settler");
Parameters
Name | Type | Description |
---|---|---|
_nftAddress | address | The address of the Settlement NFT contract. |
mintOutstandingTokensFromNft
Mint outstanding tokens for an account based on the Settler NFT held by that account.
Useful when an NFT is transferred as this function can be called before the NFT is transferred,
function mintOutstandingTokensFromNft(address account) external;
Parameters
Name | Type | Description |
---|---|---|
account | address | The account to mint tokens for. |
_mintOutstandingTokensFromNft
Internal function to mint outstanding tokens for an account based on the Settler NFT held by that account.
This function calculates the new tokens to mint and updates the state to reflect the minted tokens.
If the nftId
is zero, the function does nothing as there is no corresponding NFT for the account.
function _mintOutstandingTokensFromNft(address account) internal;
Parameters
Name | Type | Description |
---|---|---|
account | address | The account for which tokens are minted. |
_update
Override standard ERC20 _update
function.
Mints outstanding SETTLER tokens based on the Settler NFT held by the account,
then calls the parent _update
function to update the account balances.
function _update(address from, address to, uint256 value) internal override;
Parameters
Name | Type | Description |
---|---|---|
from | address | The account to transfer tokens from. |
to | address | |
value | uint256 |
balanceOf
Override standard ERC20 balanceOf
function.
If the account has an NFT, calculate the unminted balance based on the time since the NFT was minted.
function balanceOf(address account) public view override returns (uint256 accountBalance);
Parameters
Name | Type | Description |
---|---|---|
account | address | The account to get the balance of. |
Returns
Name | Type | Description |
---|---|---|
accountBalance | uint256 | The balance of the account as a sum of the minted and unminted tokens. |
_totalLifetimeTokensFromNft
Calculate the total lifetime tokens from an NFT based on the mint timestamp.
function _totalLifetimeTokensFromNft(uint256 _mintTimestamp) internal view returns (uint256 totalLifetimeTokens);
Parameters
Name | Type | Description |
---|---|---|
_mintTimestamp | uint256 | The timestamp when the NFT was minted. |
Returns
Name | Type | Description |
---|---|---|
totalLifetimeTokens | uint256 | The total lifetime tokens from the NFT. |
_calculateNewTokensToMint
Calculate the new tokens to mint for an account based on the Settler NFT held by the account.
function _calculateNewTokensToMint(address account)
internal
view
returns (uint256 nftId, uint256 totalLifetimeTokensFromNft, uint256 newTokensToMint);
Parameters
Name | Type | Description |
---|---|---|
account | address | The account to calculate the new tokens to mint for. |
Returns
Name | Type | Description |
---|---|---|
nftId | uint256 | The ID of the NFT held by the account. |
totalLifetimeTokensFromNft | uint256 | The total lifetime tokens from the NFT. |
newTokensToMint | uint256 | The new tokens to mint for the account. |
ViewAggregator
Author: EridianAlpha
An aggregator contract for multi-calling view functions on Ethereum Settlers contracts.
State Variables
SETTLEMENT_NFT
SettlementNft public immutable SETTLEMENT_NFT;
SETTLERS_TOKEN
SettlerToken public immutable SETTLERS_TOKEN;
Functions
constructor
Constructor to initialize the Settlement NFT and SETTLER token addresses.
constructor(address _nftAddress);
Parameters
Name | Type | Description |
---|---|---|
_nftAddress | address | The address of the Settlement NFT contract. |
getSequentialData
Get the sequential data for a range of NFTs.
function getSequentialData(uint256 _startingNftId, uint256 _endingNftId)
public
view
returns (SettlementData[] memory results);
Parameters
Name | Type | Description |
---|---|---|
_startingNftId | uint256 | The starting NFT ID. |
_endingNftId | uint256 | The ending NFT ID. |
Returns
Name | Type | Description |
---|---|---|
results | SettlementData[] | The array of SettlementData structs for the range of NFTs. |
getRandomData
Get a pseudo-random selection of NFTs.
This function uses pseudo-randomness as it is only used to return a selection of NFTs for display purposes. This function could have been implemented offchain but the point of this view contract is to make interacting with the contracts easier for the front-end.
function getRandomData(uint256 requestedNumber) external view returns (SettlementData[] memory results);
Parameters
Name | Type | Description |
---|---|---|
requestedNumber | uint256 | The number of NFTs to return. |
Returns
Name | Type | Description |
---|---|---|
results | SettlementData[] | The array of SettlementData structs for the random NFTs. |
_daysSinceMint
Calculates the days since mint for an NFT.
function _daysSinceMint(uint256 _mintTimestamp) internal view returns (uint256 daysSinceMint);
Parameters
Name | Type | Description |
---|---|---|
_mintTimestamp | uint256 | The timestamp when the NFT was minted. |
Returns
Name | Type | Description |
---|---|---|
daysSinceMint | uint256 | The days since the NFT was minted. |
_populateSettlementData
Populates the SettlementData struct for an NFT.
function _populateSettlementData(uint256 i) internal view returns (SettlementData memory data);
Parameters
Name | Type | Description |
---|---|---|
i | uint256 | The NFT ID. |
Returns
Name | Type | Description |
---|---|---|
data | SettlementData | The SettlementData struct for the NFT. |
Structs
SettlementData
struct SettlementData {
address owner;
uint256 daysSinceMint;
uint256 tokens;
uint256 chainId;
uint256 nftId;
}