Skip to content

Commit

Permalink
Merge pull request #527 from EYBlockchain/zepedro/restrict-erc20-amounts
Browse files Browse the repository at this point in the history
Implemented restriction for ERC20 tokens
  • Loading branch information
signorecello authored Mar 9, 2022
2 parents e5c7c28 + f0fef92 commit 4aeee1e
Show file tree
Hide file tree
Showing 9 changed files with 750 additions and 497 deletions.
10 changes: 10 additions & 0 deletions config/default.js
Original file line number Diff line number Diff line change
Expand Up @@ -211,5 +211,15 @@ module.exports = {
challenger: 'crush power outer gadget enter maze advance rather divert monster indoor axis',
liquidityProvider: 'smart base soup sister army address member poem point quick save penalty',
},
restrictions: {
erc20default: 2000,
},
},
RESTRICTIONS: [
{
name: 'MockERC20',
address: '0xB5Acbe9a0F1F8B98F3fC04471F7fE5d2c222cB44',
amount: 200,
},
],
};
11 changes: 6 additions & 5 deletions nightfall-deployer/contracts/Challenges.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ import './Stateful.sol';
contract Challenges is Stateful, Key_Registry, Config {
mapping(bytes32 => address) public committers;

function initialize() override(Stateful, Key_Registry) public initializer {
Stateful.initialize();
Key_Registry.initialize();
}
function initialize() public override(Stateful, Key_Registry, Config) initializer {
Stateful.initialize();
Key_Registry.initialize();
Config.initialize();
}

/**
/**
Check that the block correctly updates the leafCount. Note that the leafCount
is actually the value BEFORE the commitments are added to the Merkle tree.
Thus we need the prior block so that we can check it because the value should
Expand Down
32 changes: 26 additions & 6 deletions nightfall-deployer/contracts/Config.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,30 @@

pragma solidity ^0.8.0;

contract Config {
uint constant REGISTRATION_BOND = 10 wei; // TODO owner can update
uint constant BLOCK_STAKE = 1 wei;
uint constant ROTATE_PROPOSER_BLOCKS = 4;
uint constant COOLING_OFF_PERIOD = 1 weeks;
bytes32 constant ZERO = bytes32(0);
import './Ownable.sol';

contract Config is Ownable {
uint256 constant REGISTRATION_BOND = 10 wei; // TODO owner can update
uint256 constant BLOCK_STAKE = 1 wei;
uint256 constant ROTATE_PROPOSER_BLOCKS = 4;
uint256 constant COOLING_OFF_PERIOD = 1 weeks;
bytes32 constant ZERO = bytes32(0);

mapping(address => uint256) erc20limit;

function initialize() public virtual override initializer {
Ownable.initialize();
}

function getRestriction(address tokenAddr) public view returns (uint256) {
return erc20limit[tokenAddr];
}

function setRestriction(address tokenAddr, uint256 amount) external onlyOwner {
erc20limit[tokenAddr] = amount;
}

function removeRestriction(address tokenAddr) external onlyOwner {
delete erc20limit[tokenAddr];
}
}
171 changes: 94 additions & 77 deletions nightfall-deployer/contracts/Proposers.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: CC0
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
import '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol';
import '@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol';
/*
Contract to manage the creation and managment of Proposals
*/
Expand All @@ -12,84 +12,101 @@ import './Structures.sol';
import './Stateful.sol';

contract Proposers is Stateful, Structures, Config, ReentrancyGuardUpgradeable {
function initialize() public override(Stateful, Config) initializer {
Stateful.initialize();
Config.initialize();
}

function initialize() override public initializer {
Stateful.initialize();
}
/**
* Each proposer gets a chance to propose blocks for a certain time, defined
* in Ethereum blocks. After a certain number of blocks has passed, the
* proposer can be rotated by calling this function. The method for choosing
* the next proposer is simple rotation for now.
*/
function changeCurrentProposer() external {
require(block.number - state.getProposerStartBlock() > ROTATE_PROPOSER_BLOCKS,
"It's too soon to rotate the proposer");
state.setProposerStartBlock(block.number);
LinkedAddress memory currentProposer = state.getCurrentProposer();
state.setCurrentProposer(currentProposer.nextAddress);
emit NewCurrentProposer(currentProposer.nextAddress);
}

/**
* Each proposer gets a chance to propose blocks for a certain time, defined
* in Ethereum blocks. After a certain number of blocks has passed, the
* proposer can be rotated by calling this function. The method for choosing
* the next proposer is simple rotation for now.
*/
function changeCurrentProposer() external {
require(
block.number - state.getProposerStartBlock() > ROTATE_PROPOSER_BLOCKS,
"It's too soon to rotate the proposer"
);
state.setProposerStartBlock(block.number);
LinkedAddress memory currentProposer = state.getCurrentProposer();
state.setCurrentProposer(currentProposer.nextAddress);
emit NewCurrentProposer(currentProposer.nextAddress);
}

//add the proposer to the circular linked list
function registerProposer() external payable nonReentrant {
require(REGISTRATION_BOND <= msg.value, 'The registration payment is incorrect');
require(state.getProposer(msg.sender).thisAddress == address(0), 'This proposer is already registered');
// send the bond to the state contract
(bool success, ) = payable(address(state)).call{ value: REGISTRATION_BOND }("");
require(success, "Transfer failed.");
state.setBondAccount(msg.sender,REGISTRATION_BOND);
LinkedAddress memory currentProposer = state.getCurrentProposer();
// cope with this being the first proposer
if (currentProposer.thisAddress == address(0)) {
currentProposer = LinkedAddress(msg.sender, msg.sender, msg.sender);
state.setProposer(msg.sender, currentProposer);
state.setProposerStartBlock(block.number);
emit NewCurrentProposer(currentProposer.thisAddress);
} else {
// else, splice the new proposer into the circular linked list of proposers just behind the current proposer
// assume current proposer is (x,A,z) address of this proposer is B
LinkedAddress memory proposer; // proposer: (_,_,_)
proposer.thisAddress = msg.sender; // proposer: (_,B,_)
proposer.nextAddress = currentProposer.thisAddress; // proposer: (_,B,A)
proposer.previousAddress = currentProposer.previousAddress; // proposer: (x,B,A)
// pull global state
LinkedAddress memory proposersPrevious = state.getProposer(currentProposer.previousAddress);
LinkedAddress memory proposersCurrent = state.getProposer(currentProposer.thisAddress);
// updated the pulled state
proposersPrevious.nextAddress = proposer.thisAddress; // X: (u,v,B)
proposersCurrent.previousAddress = proposer.thisAddress; // current: (B,A,z)
if (proposersPrevious.thisAddress == proposersCurrent.thisAddress) { // case register second proposer
proposersCurrent.nextAddress = proposer.thisAddress; // previous and next Address is the second proposer
}
currentProposer = proposersCurrent; // ensure sync: currentProposer: (B,A,z)
// set global state to new values
if (proposersPrevious.thisAddress != proposersCurrent.thisAddress) { // not case register second proposer
state.setProposer(proposersPrevious.thisAddress, proposersPrevious);
}
state.setProposer(proposersCurrent.thisAddress, proposersCurrent);
state.setProposer(msg.sender, proposer);
//add the proposer to the circular linked list
function registerProposer() external payable nonReentrant {
require(REGISTRATION_BOND <= msg.value, 'The registration payment is incorrect');
require(
state.getProposer(msg.sender).thisAddress == address(0),
'This proposer is already registered'
);
// send the bond to the state contract
(bool success, ) = payable(address(state)).call{value: REGISTRATION_BOND}('');
require(success, 'Transfer failed.');
state.setBondAccount(msg.sender, REGISTRATION_BOND);
LinkedAddress memory currentProposer = state.getCurrentProposer();
// cope with this being the first proposer
if (currentProposer.thisAddress == address(0)) {
currentProposer = LinkedAddress(msg.sender, msg.sender, msg.sender);
state.setProposer(msg.sender, currentProposer);
state.setProposerStartBlock(block.number);
emit NewCurrentProposer(currentProposer.thisAddress);
} else {
// else, splice the new proposer into the circular linked list of proposers just behind the current proposer
// assume current proposer is (x,A,z) address of this proposer is B
LinkedAddress memory proposer; // proposer: (_,_,_)
proposer.thisAddress = msg.sender; // proposer: (_,B,_)
proposer.nextAddress = currentProposer.thisAddress; // proposer: (_,B,A)
proposer.previousAddress = currentProposer.previousAddress; // proposer: (x,B,A)
// pull global state
LinkedAddress memory proposersPrevious =
state.getProposer(currentProposer.previousAddress);
LinkedAddress memory proposersCurrent = state.getProposer(currentProposer.thisAddress);
// updated the pulled state
proposersPrevious.nextAddress = proposer.thisAddress; // X: (u,v,B)
proposersCurrent.previousAddress = proposer.thisAddress; // current: (B,A,z)
if (proposersPrevious.thisAddress == proposersCurrent.thisAddress) {
// case register second proposer
proposersCurrent.nextAddress = proposer.thisAddress; // previous and next Address is the second proposer
}
currentProposer = proposersCurrent; // ensure sync: currentProposer: (B,A,z)
// set global state to new values
if (proposersPrevious.thisAddress != proposersCurrent.thisAddress) {
// not case register second proposer
state.setProposer(proposersPrevious.thisAddress, proposersPrevious);
}
state.setProposer(proposersCurrent.thisAddress, proposersCurrent);
state.setProposer(msg.sender, proposer);
}
state.setCurrentProposer(currentProposer.thisAddress);
}
state.setCurrentProposer(currentProposer.thisAddress);
}

// Proposers are allowed to deregister themselves at any point (even if they are the current proposer)
// However, their bond is only withdrawable after the COOLING_OFF_PERIOD has passed. This ensures
// they are not the proposer of any blocks that could be challenged.
function deRegisterProposer() external {
require(state.getProposer(msg.sender).thisAddress != address(0), 'This proposer is not registered or you are not that proposer');
state.removeProposer(msg.sender);
// The msg.sender has to wait a COOLING_OFF_PERIOD from current block.timestamp
state.updateBondAccountTime(msg.sender, block.timestamp);
}
// Proposers are allowed to deregister themselves at any point (even if they are the current proposer)
// However, their bond is only withdrawable after the COOLING_OFF_PERIOD has passed. This ensures
// they are not the proposer of any blocks that could be challenged.
function deRegisterProposer() external {
require(
state.getProposer(msg.sender).thisAddress != address(0),
'This proposer is not registered or you are not that proposer'
);
state.removeProposer(msg.sender);
// The msg.sender has to wait a COOLING_OFF_PERIOD from current block.timestamp
state.updateBondAccountTime(msg.sender, block.timestamp);
}

function withdrawBond() external {
TimeLockedBond memory bond = state.getBondAccount(msg.sender);
require(bond.time + COOLING_OFF_PERIOD < block.timestamp, 'It is too soon to withdraw your bond');
require(state.getProposer(msg.sender).thisAddress == address(0), 'Cannot withdraw bond while a registered proposer');
// Zero out the entry in the bond escrow
state.setBondAccount(msg.sender,0);
state.addPendingWithdrawal(msg.sender,bond.amount);
}
function withdrawBond() external {
TimeLockedBond memory bond = state.getBondAccount(msg.sender);
require(
bond.time + COOLING_OFF_PERIOD < block.timestamp,
'It is too soon to withdraw your bond'
);
require(
state.getProposer(msg.sender).thisAddress == address(0),
'Cannot withdraw bond while a registered proposer'
);
// Zero out the entry in the bond escrow
state.setBondAccount(msg.sender, 0);
state.addPendingWithdrawal(msg.sender, bond.amount);
}
}
Loading

0 comments on commit 4aeee1e

Please sign in to comment.