This commit is contained in:
Martín Volpe 2024-04-26 11:28:55 -04:00 committed by GitHub
commit a49a4a2369
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 172 additions and 1 deletions

View File

@ -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;
}
}

View File

@ -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,