# IToken

Matt Stam (@mattstam)

IToken

An ERC20 token that maps to a Git project. Allows for: - Releases to be gated behind proposals, with vote from token owners. - Git Consensus contract to mint new tokens for commit owners. - Initial distribution to be allocated on create.

Intent is to allow tokens to be able to be minted for commit owners. To achieve this securely, implementations will need to take care of 2 things to operate under the Git Consensus Protocol: [1] Only appropriate addresses may call mint(), which in the case of the Git Consensus Protocol, need to be at least the address of the GitConsensus contract. For typical Git project usage, this should be the ONLY address. [2] The governor() must refer to the intended caller to the GitConsensus contract, which should be the Governor that handles proposals and executions for the token. If the token implementation only allows this at initialization time (the case with TokenImpl) then this governor address must be known ahead of time using address prediction (e.g. CREATE2 usage such as in GovernorFactory). The rationale behind [1] should be obvious, but [2] is a bit more subtle. Imagine the scenario in which GitConsensus does NOT require token.governor() to be the caller: Step 1: Badguy deploys a governor with its governor.token() pointing to an already existing real token. This governor implementation will also disregard a normal proposal system (e.g. it executes functions immediately if Badguy calls governor.execute(...), regardless of any governor.propose(...) being called first). Step 2: Badguy calls addCommit(...) with some commit messages that include Badguy's wallet address. Step 3: Badguy calls governor.execute(gitConsensus.addRelease(...)) with a tag message that includes to Badguy's governor address, and with a hashes & values distribution that includes the commit hashes from Step 2. The GitConsensus contract would mint these tokens to Badguy's wallet address. Solution: The IToken's govAddr can only be the caller to addRelease(...), therefore when Badguy creates a new Governor in Step 2, his new governor will have the transaction reverted.

# Methods

# governor

function governor() external nonpayable returns (address governorAddr)

Returns the governor corresponding to this token.

Assumes a 1:1 mapping between governor and token, which is not always the case with typical DAO usage. However, this is essential for tokens that want to be compatible with the Git Consensus Protocol.

# Returns

Name Type Description
governorAddr address The governor address.

# initialize

function initialize(address govAddr, address minterAddr, string name, string symbol, uint256 maxMintablePerHash, address[] owners, uint256[] values) external nonpayable

Initializes the ERC20 Token contract.

The owners and values array input is similar in format and usage to IGitConsensus addRelease(), with the difference being that the git commit hash -> address mapping is skipped, which allows addresses to be directly specified for initial ownership. If no initial distribution is desired, these arrays should be empty. In this case, anybody will be able to make the first proposal and execute it to addRelease(), in which they can define any distribution they want. So it's recommended to always just do an initial distribution here, even if token values are extremely low.

# Parameters

Name Type Description
govAddr address Address of the corresponding governor contract. Recommended usage is use address prediction to create the Token first, then create the Governor with this Token's address as the tokenAddr parameter.
minterAddr address Address of the contract that will be able to mint new tokens. Should always be set to the Git Consensus contract's address.
name string Name of the token (e.g. "MyToken").
symbol string Symbol of the token (e.g. "MTK").
maxMintablePerHash uint256 The maximum value that can be minted for a single hash in the hashes array during GitConsensus.addRelease(tagData, hashes, values). If no maximum is desired, set to 0.
owners address[] Array of addresses to receive an initial distribution of tokens. MUST equal length of values.
values uint256[] Array of amounts of tokens to be given to each owner. The initial token supply will be equal to the sum of all values. MUST equal length of owners.

# maxMintablePerHash

function maxMintablePerHash() external nonpayable returns (uint256 max)

Returns maximum value that a commit hash can recieve.

Aside from limiting the final distribution that is sent to GitConsensus.addRelease(), this value also gives clients a reference for the maximum that a voter should be able assign to a single commit during the pre-proposal stage. This pre-proposal stage allows all the voters' preferred distributions to be aggregated into the final one proposed.

# Returns

Name Type Description
max uint256 The maximum value a single commit hash can receive from the execution of GitConsensus.addRelease(). A value of 0 means there is no maximum.

# mint

function mint(address account, uint256 amount) external nonpayable

Creates amount tokens and assigns them to account, increasing the total supply.

This function is SHOULD only be callable by the minter() address, which should be the GitConsensus

# Parameters

Name Type Description
account address The address to assign the newly minted tokens to.
amount uint256 The amount of tokens to be minted.

# minter

function minter() external nonpayable returns (address minterAddr)

Returns the minter corresponding to this token.

# Returns

Name Type Description
minterAddr address The minter address, who can execute mint().

# Errors

# InitialDistributionLengthMismatch

error InitialDistributionLengthMismatch(uint256 ownersLen, uint256 valuesLen)

When distribution owner array length and values array length do not match.

Can occur with initialize().

# Parameters

Name Type Description
ownersLen uint256 The length of the owners array.
valuesLen uint256 The length of the values array.

# MaxMintablePerHashExceeded

error MaxMintablePerHashExceeded(uint256 value, uint256 maxMintableValue)

When an mint attempt occurs that exceeds the token's maxMintablePerHash().

Can occur with addRelease(). Specifically occurs when a values[i] exists the values array that is greater than the token's maxMintablePerHash().

# Parameters

Name Type Description
value uint256 The value attempting to be minted.
maxMintableValue uint256 The token's maxMintablePerHash() value.

# UnauthorizedMinter

error UnauthorizedMinter(address senderAddr, address expectedAddr)

When a mint attempt occurs from a sender other than the token's minter().

Can occur with mint().

# Parameters

Name Type Description
senderAddr address The address of the unauthorized sender.
expectedAddr address The expected address, which should be the minter.