Skip to content

Commit 245c534

Browse files
authored
CM-778 - Add multicaller contract with tests (#234)
* Add multicaller contract with tests * Added threat model * Fixing some errors with the tests * Fixes npm error * Add high level image * Fix solhint warnings/errors * Fix slither warnings * Add Readme.md inside contracts/multicall * Modify readme to add threat model * Another attempt to silence slither warning * Add exclusion for Slither Detector calls-loop
1 parent 7bd109a commit 245c534

File tree

10 files changed

+918
-21
lines changed

10 files changed

+918
-21
lines changed
665 KB
Binary file not shown.
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
## Background
2+
---
3+
Currently the Primary Sales product uses the pattern of Multicall to transfer ERC20 tokens and mint ERC721/ERC1155 tokens in a single transaction. The Multicaller contract is a common pattern in the space and is used by many projects, this has some added security features that will be mentioned below.
4+
5+
## Architecture
6+
---
7+
### Contract High-Level Design
8+
---
9+
![alt text](202309-threat-model-multicaller/high-level.png "High Level")
10+
11+
The core of the `Guarded Multi-caller` system is `Multi-call`, allowing for the minting and burning of multiple NFTs from various collections in a single transaction. Due to the high level of security needed when working with NFTs, additional safety measures have been implemented to meet security standards.
12+
13+
- `Function Permits` prevent destructive calls from being made from the Multi-caller contract.
14+
- `Signature Validation` prevents multi-call instructions from random parties and only allows multi-call instructions from trusted parties.
15+
- `Signer Access Control` manages these trusted parties.
16+
- `References` provide anti-replay protection and help sync with any web2 system listening to events.
17+
18+
### System High-Level Design
19+
---
20+
![alt text](202309-threat-model-multicaller/architecture.png "Architecture")
21+
#### Components
22+
---
23+
| Component | Ownership | Description |
24+
|------------------------------ |----------- |------------------------------------------------------------------------------------------------------------------------- |
25+
| Client | Customer | This can be a game client or a mobile client that the players interact with. |
26+
| Central Authority | Customer | It generates a list of function calls to be executed and gets a valid signature for those calls from `Multi-call Signer`. |
27+
| Multi-call Signer | Customer | It takes a list of function calls and generates a valid signature using a `EOA` with `MULTICALL_SIGNER_ROLE`. |
28+
| Guarded Multicaller Contract | Customer | It validates an input signature and executes an authorized list of function calls. |
29+
30+
#### Flow
31+
---
32+
Let’s look at the flow for basic crafting, where players burn one NFT from the `ERC721Card` contract and mint a new NFT on the `ERC721Pet` contract:
33+
34+
1. An `EOA` with `DEFAULT_ADMIN_ROLE` calls the `Guarded Multi-caller` contract to permit mint function `mint(address,uint256)` with the `ERC721Pet` contract.
35+
2. An `EOA` with `DEFAULT_ADMIN_ROLE` calls the `ERC721Pet` contract to grant `MINTER_ROLE` to the `Guarded Multi-caller` contract.
36+
3. A client requests the `Central Authority` to generate a list of function calls to burn and mint and request a signature from the `Multi-call Signer`.
37+
4. The `Multi-call Signer` uses an account with `MULTICALL_SIGNER_ROLE` to sign the function calls and returns the signature back to the `Central Authority`.
38+
5. The `Central Authority` returns the list of function calls and the signature to the client.
39+
6. The `Client` approves the `Guarded Multi-caller` contract as a spender for their `ERC721Card` NFT.
40+
7. The `Client` submits a transaction to the `Guarded Multi-caller` contract to execute the list of function calls.
41+
8. The `GuardedMulticaller` contract calls the `ERC721Card` contract to burn the NFT and calls the `ERC721Pet` contract to mint a new NFT to the player’s wallet.
42+
43+
## Public Interface
44+
---
45+
```javascript
46+
function execute(
47+
address _multicallSigner,
48+
bytes32 _ref,
49+
address[] calldata _targets,
50+
bytes[] calldata _data,
51+
uint256 _deadline,
52+
bytes calldata _signature
53+
)
54+
55+
function setFunctionPermits(
56+
address[] calldata _targets,
57+
bytes4[] calldata _functionSelectors,
58+
bool[] calldata _permitted
59+
)
60+
61+
function isFunctionPermitted(
62+
address _target,
63+
bytes4 _functionSelector
64+
)
65+
66+
function grantMulticallSignerRole(
67+
address _user
68+
)
69+
70+
function revokeMulticallSignerRole(
71+
address _user
72+
)
73+
```
74+
75+
## Security Considerations
76+
---
77+
- If the `Central Authority` is compromised, attackers are able to generate valid signatures to mint new tokens for themselves. As each customer manages their own `Central Authority`, its impact is per customer.
78+
- If the `Multi-call Signer` is compromised, attackers are able to generate valid signatures to mint new tokens for themselves. As each customer manages their own `Multi-call Signer`, its impact is per customer.
58.1 KB
Loading
38.7 KB
Loading

contracts/mocks/MockFunctions.sol

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// SPDX-License-Identifier: Unlicense
2+
// This file is part of the test code for GuardedMulticaller
3+
pragma solidity ^0.8.19;
4+
5+
contract MockFunctions {
6+
// solhint-disable-next-line no-empty-blocks
7+
function succeed() public pure {
8+
// This function is intentionally left empty to simulate a successful call
9+
}
10+
11+
function revertWithNoReason() public pure {
12+
// solhint-disable-next-line custom-errors,reason-string
13+
revert();
14+
}
15+
16+
// solhint-disable-next-line no-empty-blocks
17+
function nonPermitted() public pure {
18+
// This function is intentionally left empty to simulate a non-permitted action
19+
}
20+
}

0 commit comments

Comments
 (0)