Skip to content

Commit

Permalink
Merge pull request #260 from CMTA/ccip
Browse files Browse the repository at this point in the history
Ccip
  • Loading branch information
rya-sge authored Jan 18, 2024
2 parents 6cb947d + 3036d4c commit d4f3bc4
Show file tree
Hide file tree
Showing 20 changed files with 214 additions and 362 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ jobs:
steps:
- uses: actions/checkout@v3

- name: Setup NodeJS 16
- name: Setup NodeJS 20.5.0
uses: actions/setup-node@v3
with:
node-version: 16.17.0
node-version: 20.5.0

- name: Show NodeJS version
run: npm --version
Expand Down
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[submodule "openzeppelin-contracts-upgradeable"]
path = openzeppelin-contracts-upgradeable
url = https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable
[submodule "ccip"]
path = ccip
url = https://github.com/smartcontractkit/ccip
1 change: 1 addition & 0 deletions ccip
Submodule ccip added at 9d4d2a
20 changes: 20 additions & 0 deletions contracts/interfaces/ICCIPToken.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//SPDX-License-Identifier: MPL-2.0

pragma solidity ^0.8.0;

interface ICCIPMintERC20 {
/// @notice Mints new tokens for a given address.
/// @param account The address to mint the new tokens to.
/// @param value The number of tokens to be minted.
/// @dev this function increases the total supply.
function mint(address account, uint256 value) external;
}

interface ICCIPBurnFromERC20 {
/// @notice Burns tokens from a given address..
/// @param account The address to burn tokens from.
/// @param value The number of tokens to be burned.
/// @dev this function decreases the total supply.
function burnFrom(address account, uint256 value) external;

}
30 changes: 24 additions & 6 deletions contracts/modules/CMTAT_BASE.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ import "./wrapper/core/PauseModule.sol";
/*
SnapshotModule:
Add this import in case you add the SnapshotModule
import "./wrapper/optional/SnapshotModule.sol";
*/
import "./wrapper/extensions/ERC20SnapshotModule.sol";

import "./wrapper/controllers/ValidationModule.sol";
import "./wrapper/extensions/MetaTxModule.sol";
import "./wrapper/extensions/DebtModule/DebtBaseModule.sol";
Expand All @@ -36,7 +37,7 @@ abstract contract CMTAT_BASE is
ValidationModule,
MetaTxModule,
ERC20BaseModule,
// ERC20SnapshotModule,
ERC20SnapshotModule,
DebtBaseModule,
CreditEventsModule
{
Expand Down Expand Up @@ -110,10 +111,10 @@ abstract contract CMTAT_BASE is
/*
SnapshotModule:
Add these two calls in case you add the SnapshotModule
*/
__SnapshotModuleBase_init_unchained();
__ERC20Snapshot_init_unchained();
*/

__Validation_init_unchained(ruleEngine_);

/* Wrapper */
Expand All @@ -131,8 +132,9 @@ abstract contract CMTAT_BASE is
/*
SnapshotModule:
Add this call in case you add the SnapshotModule
__ERC20SnasphotModule_init_unchained();
*/
__ERC20SnasphotModule_init_unchained();


/* Other modules */
__DebtBaseModule_init_unchained();
Expand Down Expand Up @@ -173,6 +175,22 @@ abstract contract CMTAT_BASE is
return ERC20BaseModule.transferFrom(sender, recipient, amount);
}

/**
@notice burn and mint atomically
@param from current token holder to burn tokens
@param to receiver to send the new minted tokens
@param amountToBurn number of tokens to burn
@param amountToMint number of tokens to mint
@dev
- The access control is managed by the functions burn (ERC20BurnModule) and mint (ERC20MintModule)
- Input validation is also managed by the functions burn and mint
- You can mint more tokens than burnt
*/
function burnAndMint(address from, address to, uint256 amountToBurn, uint256 amountToMint, string calldata reason) public {
burn(from, amountToBurn, reason);
mint(to, amountToMint);
}

/**
* @dev
*
Expand All @@ -190,7 +208,7 @@ abstract contract CMTAT_BASE is
Add this in case you add the SnapshotModule
We call the SnapshotModule only if the transfer is valid
*/
// ERC20SnapshotModuleInternal._snapshotUpdate(from, to);
ERC20SnapshotModuleInternal._snapshotUpdate(from, to);
ERC20Upgradeable._update(from, to, amount);
}

Expand Down
5 changes: 3 additions & 2 deletions contracts/modules/security/AuthorizationModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ abstract contract AuthorizationModule is AccessControlUpgradeable {
event AuthorizationEngine(IAuthorizationEngine indexed newAuthorizationEngine);
// BurnModule
bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE");
bytes32 public constant BURNER_FROM_ROLE = keccak256("BURNER_FROM_ROLE");
// CreditEvents
bytes32 public constant DEBT_CREDIT_EVENT_ROLE =
keccak256("DEBT_CREDIT_EVENT_ROLE");
Expand Down Expand Up @@ -51,8 +52,8 @@ abstract contract AuthorizationModule is AccessControlUpgradeable {


/*
@notice set an authorizationEngine if not already set
@dev once an AuthorizationEngine is set, it is not possible to unset it
* @notice set an authorizationEngine if not already set
* @dev once an AuthorizationEngine is set, it is not possible to unset it
*/
function setAuthorizationEngine(
IAuthorizationEngine authorizationEngine_
Expand Down
1 change: 1 addition & 0 deletions contracts/modules/wrapper/core/BaseModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ abstract contract BaseModule is AuthorizationModule {
string public tokenId;
string public terms;
string public information;
// additional attribute to store information as an uint256
uint256 public flag;


Expand Down
1 change: 1 addition & 0 deletions contracts/modules/wrapper/core/ERC20BaseModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ abstract contract ERC20BaseModule is ERC20Upgradeable {
/* Events */
/**
* @notice Emitted when the specified `spender` spends the specified `value` tokens owned by the specified `owner` reducing the corresponding allowance.
* @dev The allowance can be also "spend" with the function BurnFrom, but in this case, the emitted event is BurnFrom.
*/
event Spend(address indexed owner, address indexed spender, uint256 value);

Expand Down
53 changes: 47 additions & 6 deletions contracts/modules/wrapper/core/ERC20BurnModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ pragma solidity ^0.8.20;
import "../../../../openzeppelin-contracts-upgradeable/contracts/token/ERC20/ERC20Upgradeable.sol";
import "../../../../openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol";
import "../../security/AuthorizationModule.sol";

abstract contract ERC20BurnModule is ERC20Upgradeable, AuthorizationModule {
import "../../../interfaces/ICCIPToken.sol";
abstract contract ERC20BurnModule is ERC20Upgradeable, ICCIPBurnFromERC20, AuthorizationModule {
/**
* @notice Emitted when the specified `value` amount of tokens owned by `owner`are destroyed with the given `reason`
*/
event Burn(address indexed owner, uint256 value, string reason);

/**
* @notice Emitted when the specified `spender` burns the specified `value` tokens owned by the specified `owner` reducing the corresponding allowance.
*/
event BurnFrom(address indexed owner, address indexed spender, uint256 value);
function __ERC20BurnModule_init_unchained() internal onlyInitializing {
// no variable to initialize
}
Expand All @@ -25,7 +28,7 @@ abstract contract ERC20BurnModule is ERC20Upgradeable, AuthorizationModule {
* Requirements:
* - the caller must have the `BURNER_ROLE`.
*/
function forceBurn(
function burn(
address account,
uint256 value,
string calldata reason
Expand All @@ -34,9 +37,10 @@ abstract contract ERC20BurnModule is ERC20Upgradeable, AuthorizationModule {
emit Burn(account, value, reason);
}


/**
*
* @notice batch version of {forceBurn}.
* @notice batch version of {burn}.
* @dev
* See {ERC20-_burn} and {OpenZeppelin ERC1155_burnBatch}.
*
Expand All @@ -48,7 +52,7 @@ abstract contract ERC20BurnModule is ERC20Upgradeable, AuthorizationModule {
* - `accounts` and `values` must have the same length
* - the caller must have the `BURNER_ROLE`.
*/
function forceBurnBatch(
function burnBatch(
address[] calldata accounts,
uint256[] calldata values,
string calldata reason
Expand All @@ -71,5 +75,42 @@ abstract contract ERC20BurnModule is ERC20Upgradeable, AuthorizationModule {
}
}

/**
* @notice Destroys `amount` tokens from `account`, deducting from the caller's
* allowance.
* @dev
* Can be used to authorize a bridge (e.g. CCIP) to burn token owned by the bridge
* No string parameter reason to be compatible with Bridge, e.g. CCIP
*
* See {ERC20-_burn} and {ERC20-allowance}.
*
* Requirements:
*
* - the caller must have allowance for ``accounts``'s tokens of at least
* `value`.
*/
function burnFrom(address account, uint256 value)
public
onlyRole(BURNER_FROM_ROLE)
{
// Allowance check
address sender = _msgSender();
uint256 currentAllowance = allowance(account, sender);
if(currentAllowance < value){
// ERC-6093
revert ERC20InsufficientAllowance(sender, currentAllowance, value);
}
// Update allowance
unchecked {
_approve(account, sender, currentAllowance - value);
}
// burn
_burn(account, value);
// We also emit a burn event since its a burn operation
emit Burn(account, value, "burnFrom");
// Specific event for the operation
emit BurnFrom(account, sender, value);
}

uint256[50] private __gap;
}
6 changes: 4 additions & 2 deletions contracts/modules/wrapper/core/ERC20MintModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ pragma solidity ^0.8.20;
import "../../../../openzeppelin-contracts-upgradeable/contracts/token/ERC20/ERC20Upgradeable.sol";
import "../../../../openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol";
import "../../security/AuthorizationModule.sol";

abstract contract ERC20MintModule is ERC20Upgradeable, AuthorizationModule {
import "../../../interfaces/ICCIPToken.sol";
abstract contract ERC20MintModule is ERC20Upgradeable, ICCIPMintERC20, AuthorizationModule {
/**
* @notice Emitted when the specified `value` amount of new tokens are created and
* allocated to the specified `account`.
Expand All @@ -19,6 +19,8 @@ abstract contract ERC20MintModule is ERC20Upgradeable, AuthorizationModule {

/**
* @notice Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0)
* @param account token receiver
* @param value amount of tokens
* @dev
* See {OpenZeppelin ERC20-_mint}.
* Emits a {Mint} event.
Expand Down
4 changes: 2 additions & 2 deletions contracts/modules/wrapper/core/EnforcementModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ abstract contract EnforcementModule is
AuthorizationModule
{
string internal constant TEXT_TRANSFER_REJECTED_FROM_FROZEN =
"The address FROM is frozen";
"Address FROM is frozen";

string internal constant TEXT_TRANSFER_REJECTED_TO_FROZEN =
"The address TO is frozen";
"Address TO is frozen";

function __EnforcementModule_init_unchained() internal onlyInitializing {
// no variable to initialize
Expand Down
Loading

0 comments on commit d4f3bc4

Please sign in to comment.