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.

ChainCommand
Anvilmake deploy anvil
Holeskymake deploy holesky
Mainnetmake deploy mainnet
Base Sepoliamake deploy base-sepolia
Base Mainnetmake 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....

ChainCommand
Anvilmake deployViewAggregator anvil
Holeskymake deployViewAggregator holesky
Mainnetmake deployViewAggregator mainnet
Base Sepoliamake deployViewAggregator base-sepolia
Base Mainnetmake 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.

ChainCommand
Anvilmake mintNft anvil
Holeskymake mintNft holesky
Mainnetmake mintNft mainnet
Base Sepoliamake mintNft base-sepolia
Base Mainnetmake 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.

ChainCommand
Anvilmake getMintTimestamp anvil
Holeskymake getMintTimestamp holesky
Mainnetmake getMintTimestamp mainnet
Base Sepoliamake getMintTimestamp base-sepolia
Base Mainnetmake getMintTimestamp base-mainnet

5.3. Get Settler Balance

Call the getSettlerBalance() function on the SettlementNft contract. Input value as an address e.g. 0x123....

ChainCommand
Anvilmake getSettlerBalance anvil
Holeskymake getSettlerBalance holesky
Mainnetmake getSettlerBalance mainnet
Base Sepoliamake getSettlerBalance base-sepolia
Base Mainnetmake 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.

ChainCommand
Anvilmake getSequentialData anvil
Holeskymake getSequentialData holesky
Mainnetmake getSequentialData mainnet
Base Sepoliamake getSequentialData base-sepolia
Base Mainnetmake 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.

ChainCommand
Anvilmake getRandomData anvil
Holeskymake getRandomData holesky
Mainnetmake getRandomData mainnet
Base Sepoliamake getRandomData base-sepolia
Base Mainnetmake getRandomData base-mainnet

6. License

MIT

SettlementNft

Git Source

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

NameTypeDescription
_baseImageUristringThe 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

NameTypeDescription
toaddressThe address to transfer the NFT to.
tokenIduint256The ID of the NFT.
authaddressThe address that is authorized to transfer the NFT.

Returns

NameTypeDescription
previousOwneraddressThe 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

NameTypeDescription
tokenIduint256The ID of the NFT.

Returns

NameTypeDescription
uristringThe 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

NameTypeDescription
tokenIduint256The ID of the NFT.

Returns

NameTypeDescription
attributesstringThe attributes for the NFT.

_generateSvg

Generates the SVG for the NFT.

function _generateSvg(uint256 tokenId) internal view returns (string memory svg);

Parameters

NameTypeDescription
tokenIduint256The ID of the NFT.

Returns

NameTypeDescription
svgstringThe 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

NameTypeDescription
tokenIdStringstringThe ID of the NFT as a string.

Returns

NameTypeDescription
rectangleSvgstringThe 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

NameTypeDescription
tokenIduint256The ID of the NFT.

Returns

NameTypeDescription
rectangleSvgstringThe 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

NameTypeDescription
_mintTimestampuint256The timestamp when the NFT was minted.

Returns

NameTypeDescription
daysSinceMintuint256The 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

NameTypeDescription
owneraddressThe address of the NFT owner.

Returns

NameTypeDescription
tokenIduint256The 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

NameTypeDescription
tokenIduint256The ID of the NFT.

Returns

NameTypeDescription
mintTimestampuint256The timestamp when the NFT was minted.

Errors

SettlementNft_SingleActivePerAddress

error SettlementNft_SingleActivePerAddress();

SettlerToken

Git Source

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

NameTypeDescription
_nftAddressaddressThe 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

NameTypeDescription
accountaddressThe 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

NameTypeDescription
accountaddressThe 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

NameTypeDescription
fromaddressThe account to transfer tokens from.
toaddress
valueuint256

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

NameTypeDescription
accountaddressThe account to get the balance of.

Returns

NameTypeDescription
accountBalanceuint256The 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

NameTypeDescription
_mintTimestampuint256The timestamp when the NFT was minted.

Returns

NameTypeDescription
totalLifetimeTokensuint256The 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

NameTypeDescription
accountaddressThe account to calculate the new tokens to mint for.

Returns

NameTypeDescription
nftIduint256The ID of the NFT held by the account.
totalLifetimeTokensFromNftuint256The total lifetime tokens from the NFT.
newTokensToMintuint256The new tokens to mint for the account.

ViewAggregator

Git Source

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

NameTypeDescription
_nftAddressaddressThe 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

NameTypeDescription
_startingNftIduint256The starting NFT ID.
_endingNftIduint256The ending NFT ID.

Returns

NameTypeDescription
resultsSettlementData[]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

NameTypeDescription
requestedNumberuint256The number of NFTs to return.

Returns

NameTypeDescription
resultsSettlementData[]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

NameTypeDescription
_mintTimestampuint256The timestamp when the NFT was minted.

Returns

NameTypeDescription
daysSinceMintuint256The 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

NameTypeDescription
iuint256The NFT ID.

Returns

NameTypeDescription
dataSettlementDataThe SettlementData struct for the NFT.

Structs

SettlementData

struct SettlementData {
    address owner;
    uint256 daysSinceMint;
    uint256 tokens;
    uint256 chainId;
    uint256 nftId;
}