---
tags: WPOKT, proposal
title: ⚔️ WPOKT UX/UI Smart Contract Scoping Document ⚔️
---
# WPOKT UX/UI Smart Contract Scoping Document
## Overview
The Pocket Foundation needs a capable ERC20 in order to bridge their native POKT token to EVM compatible chains.
## Tech Stack
- Foundry
- OpenZeppelin SC Library
- wPOKT
- ERC20
- IERC20
- ERC20Permit
- AccessControl
- Minter Contract
- Ownable
- IwPOKT Interface
### wPOKT Core Functions (18 hours)
- AccessControl Wallets:
- DEFAULT_ADMIN_ROLE: granted to a Safe multisig controlled by POKT Foundation + POKT community members
- MINTER_ROLE: granted to Minter contract which is owned by the Copper sharded wallet
- PAUSER_ROLE: granted to POKT Foundation member
- Custom AccessControl Functions:
- `mint(address user, uint256 amount, uint256 nonce) external onlyRole(MINTER_ROLE)` only callable by MINTER_ROLE contract. Increments `mapping(address => uint256) private _userNonces;` and enforces `require(nonce == _userNonces[user]++)` - `_userNonces[user] = nonce++;` prevents accidental double minting from the backend by preventing any duplicate data from successfully minting. Checks `feeFlag` and if `feeFlag == true` mints a portion of the new tokens to the `feeCollector` address. Reverts if `mintPaused == true`
- `batchMint(address[] users, uint256[] amounts, uint256[] nonces) external onlyRole(MINTER_ROLE)` calls the `mint` function in a loop
- `changeFee(uint256 newFeePoints, address feeCollector) external onlyRole(DEFAULT_ADMIN_ROLE)` only callable by DEFAULT_ADMIN_ROLE and is bounded by `MAX_FEE` `if (newFeePoints > 0)` `feeFlag = true;` `if (newFeePoints == 0)` - `feeFlag = false;`
- `pauseMint(bool status) external onlyRole(PAUSER_ROLE)` only callable by PAUSER_ROLE wallets. Sets the `mintPaused = status;` flag to block or allow minting
- `setMintCooldown(uint256 newLimit, uint256 newLimitIncreasePerSecond) external onlyRole(DEFAULT_ADMIN_ROLE` only callable by the DEFAULT_ADMIN_ROLE. Sets `newLimit` which is the maximum number of tokens that can be minted after complete cooldown. Sets `newLimitIncreasePerSecond` which is the rate that new tokens can be minted per second. We changed from the LIDO implementation because it assumes that it's contract is deployed to Ethereum mainnet - block times can vary widely crosschain so we should be using `block.timestamp` rather than the `block.number`
- Custom Mutative Public functions:
- `burn(uint256 amount, address receiver)` emits receiver address log data for consumption at the Copper backend
- Custom View Functions:
- `calculateFee(uint256 amount) public view returns (uint256 fee)` uses `BASIS_POINTS` and `feePoints` by `fee = (amount * feePoints) / BASIS_POINTS`. Requires that `amount % BASIS_POINTS == 0` to prevent rounding errors and "dust" accumulation
- `getCurrentLimit() public view returns (uint256 limit)` derives the current mintable token limit at the current timestamp
### Minter Contract (6 hours)
- Sets `IwPKT immutable wPKT;` interface in constructor.
- Custom onlyOwner functions:
- `callMint(address user, uint256 amount, uint256 nonce) public onlyOwner` and simply passes the data into the wPKT token's mint function `require(wPKT.mint(user, amount, nonce);`
- `batchMint(address[] users, uint256[] amounts, uint256[] nonces) external onlyOwner` requires that the length of all arrays match then makes call to wPKT token's mint function in a loop
### Audit Readiness (26 hours)
- Foundry test coverage > 90%
- Deployment script
- Fuzz testing
- Invariant testing
- Full Audit Readiness
- Testnet deployment