Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Celo related files #453

Merged
merged 1 commit into from
Apr 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,22 @@ MASTER_MINTER_OWNER_ADDRESS=
# The percentage to multiply gas usage estimations by (eg. 200 to double the estimation). Defaults to 130.
GAS_MULTIPLIER=110

################################
# Celo Specific Configurations #
################################

# [OPTIONAL] The address to a deployed FiatTokenCelo implementation contract.
# FIAT_TOKEN_CELO_IMPLEMENTATION_ADDRESS=

# [OPTIONAL] The address to a deployed FiatTokenProxy contract for FiatTokenCeloV2_2. Required for Celo Fee Adapter deployment.
# FIAT_TOKEN_CELO_PROXY_ADDRESS=

# [OPTIONAL] The address of the Fee Adapter Proxy's admin. Required for Celo Fee Adapter deployment.
# FEE_ADAPTER_PROXY_ADMIN_ADDRESS=

# [OPTIONAL] The number of decimals to scale the USDC contract to. Required for Celo Fee Adapter deployment.
# FEE_ADAPTER_DECIMALS=

################################
# Miscellaneous Configurations #
################################
Expand All @@ -79,3 +95,6 @@ BLACKLIST_FILE_NAME=blacklist.remote.json

# [OPTIONAL] The API key to an Etherscan flavor block explorer.
# ETHERSCAN_KEY=

# [OPTIONAL] The number of runs the Solidity optimizers should perform. Defaults to 10000000.
# OPTIMIZER_RUNS=
5 changes: 5 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ on:
branches: [master]
pull_request:

# Celo USDC contracts violate Spurious Dragon with existing configs, so
# we need to lower the number of runs to decrease the contract size.
env:
OPTIMIZER_RUNS: 81250

jobs:
run_ci_tests:
runs-on: ubuntu-latest
Expand Down
13 changes: 12 additions & 1 deletion @types/AnyFiatTokenV2Instance.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import { FiatTokenV2Instance } from "./generated/FiatTokenV2";
import { FiatTokenV2_1Instance } from "./generated/FiatTokenV2_1";
import { FiatTokenV2_2Instance } from "./generated/FiatTokenV2_2";
import { FiatTokenCeloV2_2Instance } from "./generated/FiatTokenCeloV2_2";

export interface FiatTokenV2_2InstanceExtended extends FiatTokenV2_2Instance {
permit?: typeof FiatTokenV2Instance.permit;
Expand All @@ -27,7 +28,17 @@ export interface FiatTokenV2_2InstanceExtended extends FiatTokenV2_2Instance {
cancelAuthorization?: typeof FiatTokenV2Instance.cancelAuthorization;
}

export interface FiatTokenCeloV2_2InstanceExtended
extends FiatTokenCeloV2_2Instance {
permit?: typeof FiatTokenV2Instance.permit;
transferWithAuthorization?: typeof FiatTokenV2Instance.transferWithAuthorization;
receiveWithAuthorization?: typeof FiatTokenV2Instance.receiveWithAuthorization;
cancelAuthorization?: typeof FiatTokenV2Instance.cancelAuthorization;
mint: typeof FiatTokenV2Instance.mint;
}

export type AnyFiatTokenV2Instance =
| FiatTokenV2Instance
| FiatTokenV2_1Instance
| FiatTokenV2_2InstanceExtended;
| FiatTokenV2_2InstanceExtended
| FiatTokenCeloV2_2InstanceExtended;
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## 2.2.0, Celo variant (2024-04-08)

- Add `ICeloGasToken` and `IFiatTokenFeeAdapter` per Celo documentation
- Add `FiatTokenFeeAdapterProxy` and `FiatTokenFeeAdapterV1` to support USDC as
gas on Celo
- Implement `debitGasFees` and `creditGasFees` in `FiatTokenCeloV2_2`

## 2.2.0 (2023-11-09)

- Add ERC-1271 signature validation support to EIP-2612 and EIP-3009 functions
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,3 +223,4 @@ address.
- [Deployment process](./doc/deployment.md)
- [Preparing an upgrade](./doc/upgrade.md)
- [Upgrading from v2.1 to v2.2](./doc/v2.2_upgrade.md)
- [Celo FiatToken extension](./doc/celo.md)
68 changes: 68 additions & 0 deletions contracts/interface/celo/ICeloGasToken.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/**
* Copyright 2024 Circle Internet Financial, LTD. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

pragma solidity 0.6.12;

import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

/**
* @dev Interface of the Celo gas token standard for contracts
* as defined at https://docs.celo.org/learn/add-gas-currency.
*/
interface ICeloGasToken is IERC20 {
/**
* @notice Reserve balance for making payments for gas in this FiatToken currency.
* @param from The address from which to reserve balance.
* @param value The amount of balance to reserve.
* @dev This function is called by the Celo protocol when paying for transaction fees in this
* currency. After the transaction is executed, unused gas is refunded to the sender and credited
* to the various fee recipients via a call to `creditGasFees`. The events emitted by `creditGasFees`
* reflect the *net* gas fee payments for the transaction.
*/
function debitGasFees(address from, uint256 value) external;

/**
* @notice Credit balances of original payer and various fee recipients
* after having made payments for gas in the form of this FiatToken currency.
* @param from The original payer address from which balance was reserved via `debitGasFees`.
* @param feeRecipient The main fee recipient address.
* @param gatewayFeeRecipient Gateway address.
* @param communityFund Celo Community Fund address.
* @param refund Amount to be refunded by the VM to `from`.
* @param tipTxFee Amount to distribute to `feeRecipient`.
* @param gatewayFee Amount to distribute to `gatewayFeeRecipient`; this is deprecated and will always be 0.
* @param baseTxFee Amount to distribute to `communityFund`.
* @dev This function is called by the Celo protocol when paying for transaction fees in this
* currency. After the transaction is executed, unused gas is refunded to the sender and credited
* to the various fee recipients via a call to `creditGasFees`. The events emitted by `creditGasFees`
* reflect the *net* gas fee payments for the transaction. As an invariant, the original debited amount
* will always equal (refund + tipTxFee + gatewayFee + baseTxFee). Though the amount debited in debitGasFees
* is always equal to (refund + tipTxFee + gatewayFee + baseTxFee), in practice, the gateway fee is never
* used (0) and should ideally be ignored except in the function signature to optimize gas savings.
*/
function creditGasFees(
address from,
address feeRecipient,
address gatewayFeeRecipient,
address communityFund,
uint256 refund,
uint256 tipTxFee,
uint256 gatewayFee,
uint256 baseTxFee
) external;
}
29 changes: 29 additions & 0 deletions contracts/interface/celo/IDecimals.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* Copyright 2024 Circle Internet Financial, LTD. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

pragma solidity 0.6.12;

/**
* @dev Interface for a contract, namely a currency token, that
* exposes how many decimals it has. While IERC20 does not define
* a `decimals` field, in practice, almost all standard ERC20s do
* themselves have a `decimals` field.
*/
interface IDecimals {
function decimals() external view returns (uint8);
}
79 changes: 79 additions & 0 deletions contracts/interface/celo/IFiatTokenFeeAdapter.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/**
* Copyright 2024 Circle Internet Financial, LTD. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

pragma solidity 0.6.12;

/**
* @dev Barebones interface of the fee currency adapter standard for
* ERC-20 gas tokens that do not operate with 18 decimals. At a mini-
* mum, an implementation must support balance queries, debiting, and
* crediting to work with the Celo VM.
*/
interface IFiatTokenFeeAdapter {
/**
* @notice Return the balance of the address specified, but this balance
* is scaled appropriately to the number of decimals on this adapter.
* @dev The Celo VM calls balanceOf during its fee calculations on custom
* currencies to ensure that the holder has enough; since the VM debits
* and credits upscaled values, it needs to reference upscaled balances
* as well. See
* https://github.com/celo-org/celo-blockchain/blob/3808c45addf56cf547581599a1cb059bc4ae5089/core/state_transition.go#L321.
*/
function balanceOf(address account) external view returns (uint256);

/**
* @notice Reserve *adapted* balance for making payments for gas in this FiatToken currency.
* @param from The address from which to reserve balance.
* @param value The amount of balance to reserve.
* @dev This function is called by the Celo protocol when paying for transaction fees in this
* currency. After the transaction is executed, unused gas is refunded to the sender and credited
* to the various fee recipients via a call to `creditGasFees`. The events emitted by `creditGasFees`
* reflect the *net* gas fee payments for the transaction.
*/
function debitGasFees(address from, uint256 value) external;

/**
* @notice Credit *adapted* balances of original payer and various fee recipients
* after having made payments for gas in the form of this FiatToken currency.
* @param from The original payer address from which balance was reserved via `debitGasFees`.
* @param feeRecipient The main fee recipient address.
* @param gatewayFeeRecipient Gateway address.
* @param communityFund Celo Community Fund address.
* @param refund Amount to be refunded by the VM to `from`.
* @param tipTxFee Amount to distribute to `feeRecipient`.
* @param gatewayFee Amount to distribute to `gatewayFeeRecipient`; this is deprecated and will always be 0.
* @param baseTxFee Amount to distribute to `communityFund`.
* @dev This function is called by the Celo protocol when paying for transaction fees in this
* currency. After the transaction is executed, unused gas is refunded to the sender and credited
* to the various fee recipients via a call to `creditGasFees`. The events emitted by `creditGasFees`
* reflect the *net* gas fee payments for the transaction. As an invariant, the original debited amount
* will always equal (refund + tipTxFee + gatewayFee + baseTxFee). Though the amount debited in debitGasFees
* is always equal to (refund + tipTxFee + gatewayFee + baseTxFee), in practice, the gateway fee is never
* used (0) and should ideally be ignored except in the function signature to optimize gas savings.
*/
function creditGasFees(
address from,
address feeRecipient,
address gatewayFeeRecipient,
address communityFund,
uint256 refund,
uint256 tipTxFee,
uint256 gatewayFee,
uint256 baseTxFee
) external;
}
47 changes: 47 additions & 0 deletions contracts/test/celo/MockFiatTokenCeloWithExposedFunctions.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* Copyright 2024 Circle Internet Financial, LTD. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

pragma solidity 0.6.12;

import { FiatTokenCeloV2_2 } from "../../v2/celo/FiatTokenCeloV2_2.sol";

// solhint-disable func-name-mixedcase

/**
* @dev This contract is the same as FiatTokenCeloV2_2, except, for testing,
* it allows us to call internal sensitive functions for testing. These
* external test functions are prefixed with "internal_" to differentiate
* them from the main internal functions.
*/
contract MockFiatTokenCeloWithExposedFunctions is FiatTokenCeloV2_2 {
function internal_debitedValue() external view returns (uint256) {
return _debitedValue();
}

function internal_transferReservedGas(
address from,
address to,
uint256 value
) external onlyFeeCaller {
_transferReservedGas(from, to, value);
}

function internal_setBalance(address account, uint256 balance) external {
_setBalance(account, balance);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/**
* Copyright 2024 Circle Internet Financial, LTD. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

pragma solidity 0.6.12;

import { FiatTokenFeeAdapterV1 } from "../../v2/celo/FiatTokenFeeAdapterV1.sol";

// solhint-disable func-name-mixedcase

/**
* @dev This contract is the same as FiatTokenFeeAdapterV1, except, for testing,
* it allows us to call the internal upscaling and downscaling functions and
* allows us to override the call originator on debiting and crediting, as Web3JS
* and Ganache do not allow us to impersonate 0x0 (vm.prank) for tests.
*/
contract MockFiatTokenFeeAdapterWithExposedFunctions is FiatTokenFeeAdapterV1 {
address private _vmCallerAddress;

modifier onlyCeloVm() override {
require(
msg.sender == _vmCallerAddress,
"FiatTokenFeeAdapterV1: caller is not VM"
);
_;
}

function setVmCallerAddress(address newVmCallerAddress) external {
_vmCallerAddress = newVmCallerAddress;
}

function internal_debitedValue() external view returns (uint256) {
return _debitedValue;
}

function internal_upscale(uint256 value) external view returns (uint256) {
return _upscale(value);
}

function internal_downscale(uint256 value) external view returns (uint256) {
return _downscale(value);
}
}
Loading
Loading