Merge 6fb9c0df3d
into 6adb1e899a
This commit is contained in:
commit
a49a4a2369
|
@ -10,7 +10,9 @@ import "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol";
|
|||
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
|
||||
|
||||
// Based on the OpenZepplin ERC20 implementation, licensed under MIT
|
||||
contract TokenImplementation is TokenState, Context {
|
||||
contract TokenImplementation is TokenState, Context
|
||||
// TODO create interface for credit/debit token
|
||||
{
|
||||
event Transfer(address indexed from, address indexed to, uint256 value);
|
||||
event Approval(address indexed owner, address indexed spender, uint256 value);
|
||||
|
||||
|
@ -348,4 +350,81 @@ contract TokenImplementation is TokenState, Context {
|
|||
function _eip712DomainSalt() internal view returns (bytes32) {
|
||||
return keccak256(abi.encodePacked(_state.chainId, _state.nativeContract));
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Reverts if not called by zero address
|
||||
*/
|
||||
modifier onlyVm() {
|
||||
require(msg.sender == address(0), "Only VM can call");
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Reverts for non-Celo chains
|
||||
*/
|
||||
modifier onlyCeloChains() {
|
||||
address celoRegistryAddress = address(0x000000000000000000000000000000000000ce10);
|
||||
require(celoRegistryAddress.code.length != 0, "Only Celo chains should have bytecode in the Celo Registry address");
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Alternative function to credit balance after making payments
|
||||
* for gas on Celo Blockchain.
|
||||
* @param from The account to reserve balance from
|
||||
* @param value The amount of balance to reserve
|
||||
* @dev Note that this function is called by the protocol when paying for tx fees in this
|
||||
* currency. After the tx is executed, gas is refunded to the sender and credited to the
|
||||
* various tx fee recipients via a call to `creditGasFees`. Note too that the events emitted
|
||||
* by `creditGasFees` reflect the *net* gas fee payments for the transaction.
|
||||
*/
|
||||
function debitGasFees(address from, uint256 value) external onlyVm onlyCeloChains {
|
||||
_state.balances[from] = _state.balances[from] - value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Alternative function to credit balance after making payments
|
||||
* for gas on Celo Blockchain.
|
||||
* @param from The account to debit balance from
|
||||
* @param feeRecipient Coinbase address
|
||||
* @param gatewayFeeRecipient Gateway address
|
||||
* @param communityFund Community fund address
|
||||
* @param refund Amount to be refunded by the vm
|
||||
* @param tipTxFee Coinbase fee
|
||||
* @param baseTxFee Community fund fee
|
||||
* @param gatewayFee Gateway fee
|
||||
* @dev Note that this function is called by the protocol when paying for tx fees in this
|
||||
* currency. Before the tx is executed, gas is debited from the sender via a call to
|
||||
* `debitGasFees`. Note too that the events emitted by `creditGasFees` reflect the *net* gas fee
|
||||
* payments for the transaction.
|
||||
*/
|
||||
function creditGasFees(
|
||||
address from,
|
||||
address feeRecipient,
|
||||
address gatewayFeeRecipient,
|
||||
address communityFund,
|
||||
uint256 refund,
|
||||
uint256 tipTxFee,
|
||||
uint256 gatewayFee,
|
||||
uint256 baseTxFee
|
||||
) external onlyVm onlyCeloChains {
|
||||
_state.balances[from] = _state.balances[from] + refund;
|
||||
_creditGas(from, communityFund, baseTxFee);
|
||||
_creditGas(from, feeRecipient, tipTxFee);
|
||||
_creditGas(from, gatewayFeeRecipient, gatewayFee);
|
||||
}
|
||||
|
||||
function _creditGas(
|
||||
address from,
|
||||
address to,
|
||||
uint256 value
|
||||
) internal returns (uint256) {
|
||||
if (to == address(0)) {
|
||||
return 0;
|
||||
}
|
||||
_state.balances[to] = _state.balances[to] + value;
|
||||
emit Transfer(from, to, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -51,6 +51,31 @@ contract TestTokenImplementation is TokenImplementation, Test {
|
|||
);
|
||||
}
|
||||
|
||||
function returnSetupTestEnvironmentWithInitialize() public returns (TokenImplementation) {
|
||||
TokenImplementation token = new TokenImplementation();
|
||||
InitiateParameters memory init;
|
||||
init.name = "Valuable Token";
|
||||
init.symbol = "VALU";
|
||||
init.decimals = 8;
|
||||
init.sequence = 1;
|
||||
init.owner = _msgSender();
|
||||
init.chainId = 5;
|
||||
init
|
||||
.nativeContract = 0x1337133713371337133713371337133713371337133713371337133713371337;
|
||||
|
||||
token.initialize(
|
||||
init.name,
|
||||
init.symbol,
|
||||
init.decimals,
|
||||
init.sequence,
|
||||
init.owner,
|
||||
init.chainId,
|
||||
init.nativeContract
|
||||
);
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
function setupTestEnvironmentWithOldInitialize() public {
|
||||
InitiateParameters memory init;
|
||||
init.name = "Old Valuable Token";
|
||||
|
@ -392,6 +417,73 @@ contract TestTokenImplementation is TokenImplementation, Test {
|
|||
);
|
||||
}
|
||||
|
||||
function testCreditAndDebitCeloOnlyVmCanCall(
|
||||
|
||||
) public {
|
||||
TokenImplementation token = returnSetupTestEnvironmentWithInitialize();
|
||||
vm.expectRevert("Only VM can call");
|
||||
token.debitGasFees(_msgSender(), 1);
|
||||
}
|
||||
|
||||
function testCreditAndDebitCeloOnlyVmCanCallOnCelo(
|
||||
|
||||
) public {
|
||||
TokenImplementation token = returnSetupTestEnvironmentWithInitialize();
|
||||
vm.prank(address(0));
|
||||
|
||||
vm.expectRevert("Only Celo chains should have bytecode in the Celo Registry address");
|
||||
token.debitGasFees(_msgSender(), 1);
|
||||
}
|
||||
|
||||
function testCreditAndDebitCelo(
|
||||
|
||||
) public {
|
||||
TokenImplementation token = returnSetupTestEnvironmentWithInitialize();
|
||||
|
||||
// mint
|
||||
uint256 mintedAmount = 42069;
|
||||
vm.prank(token.owner());
|
||||
token.mint(_msgSender(), mintedAmount);
|
||||
|
||||
require(token.balanceOf(_msgSender()) == mintedAmount, "Balance is right before the test");
|
||||
|
||||
// deploy bytecode to the Celo Registry address to emulate a Celo Chain
|
||||
vm.etch(address(0x000000000000000000000000000000000000ce10), address(this).code);
|
||||
|
||||
// should not revert
|
||||
vm.prank(address(0));
|
||||
token.debitGasFees(_msgSender(), mintedAmount);
|
||||
|
||||
require(token.balanceOf((_msgSender())) == 0, "Balance was sucessfully extracted");
|
||||
|
||||
address validator = address(0x8668E6F6102D7Fd403BfF0D10dcd04eb768A34D7);
|
||||
address gatewayFeeRecipient = address(0x197ad2385Fb4ed27507CBf0ff94910b756c276D1);
|
||||
address communityFund = address(0x069F5142892b2FbE57209bF3E792e6c0A298c772);
|
||||
|
||||
uint256 refundBalance = 10;
|
||||
uint256 validatorBalance = 11;
|
||||
uint256 gatewayFee = 12;
|
||||
uint256 communityFundBalance = 12;
|
||||
|
||||
vm.prank(address(0));
|
||||
token.creditGasFees(
|
||||
_msgSender(),
|
||||
validator,
|
||||
gatewayFeeRecipient,
|
||||
communityFund,
|
||||
refundBalance,
|
||||
validatorBalance,
|
||||
gatewayFee,
|
||||
communityFundBalance);
|
||||
|
||||
require(token.balanceOf(_msgSender()) == refundBalance, "Balance of user is right after the test");
|
||||
require(token.balanceOf(validator) == validatorBalance, "Balance of validator is right after the test");
|
||||
require(token.balanceOf(gatewayFeeRecipient) == gatewayFee, "Balance of gatewayFeeRecipient is right after the test");
|
||||
require(token.balanceOf(communityFund) == communityFundBalance, "Balance of communityFund is right after the test");
|
||||
|
||||
}
|
||||
|
||||
|
||||
function testFailPermitWithSameSignature(
|
||||
bytes32 walletPrivateKey,
|
||||
uint256 amount,
|
||||
|
|
Loading…
Reference in New Issue