Skip to content
This repository was archived by the owner on Aug 21, 2023. It is now read-only.

Commit f13d8d6

Browse files
authored
Merge pull request #35 from bugout-dev/fix-safe-batch-transfer-from
Added fix for "safeBatchTransferFrom" issue
2 parents e0cd48e + 85e1f2a commit f13d8d6

7 files changed

Lines changed: 582 additions & 7 deletions

File tree

contracts/terminus/ERC1155WithTerminusStorage.sol

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,11 @@ contract ERC1155WithTerminusStorage is
275275
uint256 id = ids[i];
276276
uint256 amount = amounts[i];
277277

278+
require(
279+
!ts.poolNotTransferable[id],
280+
"ERC1155WithTerminusStorage: _safeBatchTransferFrom -- pool is not transferable"
281+
);
282+
278283
uint256 fromBalance = ts.poolBalances[id][from];
279284
require(
280285
fromBalance >= amount,

dao/core.py

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ def facet_cut(
5252
initializer_address: str = ZERO_ADDRESS,
5353
ignore_methods: Optional[List[str]] = None,
5454
ignore_selectors: Optional[List[str]] = None,
55+
methods: Optional[List[str]] = None,
56+
selectors: Optional[List[str]] = None,
5557
) -> Any:
5658
"""
5759
Cuts the given facet onto the given Diamond contract.
@@ -70,6 +72,10 @@ def facet_cut(
7072
ignore_methods = []
7173
if ignore_selectors is None:
7274
ignore_selectors = []
75+
if methods is None:
76+
methods = []
77+
if selectors is None:
78+
selectors = []
7379

7480
project_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
7581
abis = abi.project_abis(project_dir)
@@ -86,15 +92,26 @@ def facet_cut(
8692

8793
facet_function_selectors: List[str] = []
8894
facet_abi = abis.get(facet_name, [])
95+
96+
logical_operator = all
97+
method_predicate = lambda method: method not in ignore_methods
98+
selector_predicate = (
99+
lambda selector: selector not in reserved_selectors
100+
and selector not in ignore_selectors
101+
)
102+
103+
if len(methods) > 0 or len(selectors) > 0:
104+
logical_operator = any
105+
method_predicate = lambda method: method in methods
106+
selector_predicate = lambda selector: selector in selectors
107+
89108
for item in facet_abi:
90109
if item["type"] == "function":
91-
if item["name"] not in ignore_methods:
92-
function_selector = abi.encode_function_signature(item)
93-
if (
94-
function_selector not in reserved_selectors
95-
and function_selector not in ignore_selectors
96-
):
97-
facet_function_selectors.append(function_selector)
110+
item_selector = abi.encode_function_signature(item)
111+
if logical_operator(
112+
[method_predicate(item["name"]), selector_predicate(item_selector)]
113+
):
114+
facet_function_selectors.append(item_selector)
98115

99116
target_address = facet_address
100117
if FACET_ACTIONS[action] == 2:
@@ -218,6 +235,8 @@ def handle_facet_cut(args: argparse.Namespace) -> None:
218235
initializer_address=args.initializer_address,
219236
ignore_methods=args.ignore_methods,
220237
ignore_selectors=args.ignore_selectors,
238+
methods=args.methods,
239+
selectors=args.selectors,
221240
)
222241

223242

@@ -277,6 +296,16 @@ def generate_cli() -> argparse.ArgumentParser:
277296
nargs="+",
278297
help="Method selectors to ignore when cutting a facet onto or off of the diamond",
279298
)
299+
facet_cut_parser.add_argument(
300+
"--methods",
301+
nargs="+",
302+
help="Names of methods to add (if set, --ignore-methods and --ignore-selectors are not used)",
303+
)
304+
facet_cut_parser.add_argument(
305+
"--selectors",
306+
nargs="+",
307+
help="Selectors to add (if set, --ignore-methods and --ignore-selectors are not used)",
308+
)
280309
facet_cut_parser.set_defaults(func=handle_facet_cut)
281310

282311
gogogo_parser = subcommands.add_parser("gogogo")

dao/test_terminus.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,58 @@ def test_burnable_pool_burn_as_unauthorized_third_party(self):
742742
self.assertEqual(final_pool_supply, initial_pool_supply)
743743
self.assertEqual(final_owner_balance, initial_owner_balance)
744744

745+
def test_nontransferable_pool_safe_transfer_from(self):
746+
self.diamond_terminus.create_pool_v1(10, False, False, {"from": accounts[1]})
747+
pool_id = self.diamond_terminus.total_pools()
748+
self.diamond_terminus.mint(accounts[2], pool_id, 1, b"", {"from": accounts[1]})
749+
750+
initial_pool_supply = self.diamond_terminus.terminus_pool_supply(pool_id)
751+
initial_owner_balance = self.diamond_terminus.balance_of(
752+
accounts[2].address, pool_id
753+
)
754+
with self.assertRaises(Exception):
755+
self.diamond_terminus.safe_transfer_from(
756+
accounts[2].address,
757+
accounts[3].address,
758+
pool_id,
759+
1,
760+
b"",
761+
{"from": accounts[2]},
762+
)
763+
764+
final_pool_supply = self.diamond_terminus.terminus_pool_supply(pool_id)
765+
final_owner_balance = self.diamond_terminus.balance_of(
766+
accounts[2].address, pool_id
767+
)
768+
self.assertEqual(final_pool_supply, initial_pool_supply)
769+
self.assertEqual(final_owner_balance, initial_owner_balance)
770+
771+
def test_nontransferable_pool_safe_batch_transfer_from(self):
772+
self.diamond_terminus.create_pool_v1(10, False, False, {"from": accounts[1]})
773+
pool_id = self.diamond_terminus.total_pools()
774+
self.diamond_terminus.mint(accounts[2], pool_id, 1, b"", {"from": accounts[1]})
775+
776+
initial_pool_supply = self.diamond_terminus.terminus_pool_supply(pool_id)
777+
initial_owner_balance = self.diamond_terminus.balance_of(
778+
accounts[2].address, pool_id
779+
)
780+
with self.assertRaises(Exception):
781+
self.diamond_terminus.safe_batch_transfer_from(
782+
accounts[2].address,
783+
accounts[3].address,
784+
[pool_id],
785+
[1],
786+
b"",
787+
{"from": accounts[2]},
788+
)
789+
790+
final_pool_supply = self.diamond_terminus.terminus_pool_supply(pool_id)
791+
final_owner_balance = self.diamond_terminus.balance_of(
792+
accounts[2].address, pool_id
793+
)
794+
self.assertEqual(final_pool_supply, initial_pool_supply)
795+
self.assertEqual(final_owner_balance, initial_owner_balance)
796+
745797

746798
if __name__ == "__main__":
747799
unittest.main()
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
# Update the Terminus contract
2+
3+
The Terminus contract is deployed as an EIP2535 Diamond proxy contract with a Terminus facet attached to it.
4+
5+
This checklist describes how to update the `TerminusFacet` on the Terminus diamond contract.
6+
7+
## Purpose of update
8+
9+
Make `safeBatchTransferFrom` respect non-transferable Terminus pools. (And add `setController`.)
10+
11+
12+
## Environment variables
13+
14+
- [x] `export DAO_NETWORK=polygon-main`
15+
- [x] `export DAO_OWNER=<redacted>`
16+
- [x] `export DAO_OWNER_ADDRESS=$(jq -r .address $DAO_OWNER)`
17+
- [x] `export GAS_PRICE="80 gwei"`
18+
- [x] `export CONFIRMATIONS=5`
19+
- [x] `export TERMINUS_DIAMOND=0x99A558BDBdE247C2B2716f0D4cFb0E246DFB697D`
20+
- [x] `export TERMINUS_FACET_ADDRESS="0xaA91032E567fD3CF2e7102f65B1AaF21530583a0"`
21+
22+
- [x] Build [Inspector Facet](https://github.com/bugout-dev/inpsector-facet) report for Diamond contract:
23+
24+
```
25+
- - -
26+
Facet at address: 0x539d0E4A68F720b35c1670B6421673a852de52DB
27+
Possible contracts: IDiamondCut, DiamondCutFacet
28+
IDiamondCut:
29+
Missing methods:
30+
Mounted selectors:
31+
Selector: 0x1f931c1c, Function: diamondCut
32+
DiamondCutFacet:
33+
Missing methods:
34+
Mounted selectors:
35+
Selector: 0x1f931c1c, Function: diamondCut
36+
- - -
37+
Facet at address: 0x024e974B4524f245fE3da60CbD70EC62875f8194
38+
Possible contracts: DiamondLoupeFacet
39+
DiamondLoupeFacet:
40+
Missing methods:
41+
Mounted selectors:
42+
Selector: 0xcdffacc6, Function: facetAddress
43+
Selector: 0x52ef6b2c, Function: facetAddresses
44+
Selector: 0xadfca15e, Function: facetFunctionSelectors
45+
Selector: 0x7a0ed627, Function: facets
46+
Selector: 0x01ffc9a7, Function: supportsInterface
47+
- - -
48+
Facet at address: 0x35f2d4877C7a468eA76f2D6666d3D8a487D73A9B
49+
Possible contracts: OwnershipFacet, IERC173
50+
OwnershipFacet:
51+
Missing methods:
52+
Mounted selectors:
53+
Selector: 0x8da5cb5b, Function: owner
54+
Selector: 0xf2fde38b, Function: transferOwnership
55+
IERC173:
56+
Missing methods:
57+
Mounted selectors:
58+
Selector: 0x8da5cb5b, Function: owner
59+
Selector: 0xf2fde38b, Function: transferOwnership
60+
- - -
61+
Facet at address: 0x6396813307826Fb315e65CA7138A41CFa09a8AB3
62+
Possible contracts: TerminusFacet
63+
TerminusFacet:
64+
Missing methods:
65+
Missing selector: 0x01ffc9a7, Function: supportsInterface
66+
Mounted selectors:
67+
Selector: 0x85bc82e2, Function: approveForPool
68+
Selector: 0x00fdd58e, Function: balanceOf
69+
Selector: 0x4e1273f4, Function: balanceOfBatch
70+
Selector: 0xf5298aca, Function: burn
71+
Selector: 0xe8a3d485, Function: contractURI
72+
Selector: 0x3bad2d82, Function: createPoolV1
73+
Selector: 0xb507ef52, Function: createSimplePool
74+
Selector: 0xe985e9c5, Function: isApprovedForAll
75+
Selector: 0x027b3fc2, Function: isApprovedForPool
76+
Selector: 0x731133e9, Function: mint
77+
Selector: 0x1f7fdffa, Function: mintBatch
78+
Selector: 0x3013ce29, Function: paymentToken
79+
Selector: 0x8925d013, Function: poolBasePrice
80+
Selector: 0x21adca96, Function: poolMintBatch
81+
Selector: 0x2eb2c2d6, Function: safeBatchTransferFrom
82+
Selector: 0xf242432a, Function: safeTransferFrom
83+
Selector: 0xa22cb465, Function: setApprovalForAll
84+
Selector: 0x938e3d7b, Function: setContractURI
85+
Selector: 0x92eefe9b, Function: setController
86+
Selector: 0x6a326ab1, Function: setPaymentToken
87+
Selector: 0x78cf2e84, Function: setPoolBasePrice
88+
Selector: 0xdc55d0b2, Function: setPoolController
89+
Selector: 0x862440e2, Function: setURI
90+
Selector: 0x366e59e3, Function: terminusController
91+
Selector: 0x5dc8bdf8, Function: terminusPoolCapacity
92+
Selector: 0xd0c402e5, Function: terminusPoolController
93+
Selector: 0xa44cfc82, Function: terminusPoolSupply
94+
Selector: 0xab3c7e52, Function: totalPools
95+
Selector: 0x0e89341c, Function: uri
96+
Selector: 0x0e7afec5, Function: withdrawPayments
97+
```
98+
99+
- [x] Replace existing `TerminusFacet` methods on diamond:
100+
101+
```bash
102+
dao core facet-cut \
103+
--address $TERMINUS_DIAMOND \
104+
--network $DAO_NETWORK \
105+
--sender $DAO_OWNER \
106+
--gas-price "$GAS_PRICE" \
107+
--confirmations $CONFIRMATIONS \
108+
--facet-name TerminusFacet \
109+
--facet-address $TERMINUS_FACET_ADDRESS \
110+
--action replace
111+
```
112+
113+
- [ ] Build [Inspector Facet](https://github.com/bugout-dev/inpsector-facet) report for Diamond contract:
114+
115+
```
116+
- - -
117+
Facet at address: 0x539d0E4A68F720b35c1670B6421673a852de52DB
118+
Possible contracts: IDiamondCut, DiamondCutFacet
119+
IDiamondCut:
120+
Missing methods:
121+
Mounted selectors:
122+
Selector: 0x1f931c1c, Function: diamondCut
123+
DiamondCutFacet:
124+
Missing methods:
125+
Mounted selectors:
126+
Selector: 0x1f931c1c, Function: diamondCut
127+
- - -
128+
Facet at address: 0x024e974B4524f245fE3da60CbD70EC62875f8194
129+
Possible contracts: DiamondLoupeFacet
130+
DiamondLoupeFacet:
131+
Missing methods:
132+
Mounted selectors:
133+
Selector: 0xcdffacc6, Function: facetAddress
134+
Selector: 0x52ef6b2c, Function: facetAddresses
135+
Selector: 0xadfca15e, Function: facetFunctionSelectors
136+
Selector: 0x7a0ed627, Function: facets
137+
Selector: 0x01ffc9a7, Function: supportsInterface
138+
- - -
139+
Facet at address: 0x35f2d4877C7a468eA76f2D6666d3D8a487D73A9B
140+
Possible contracts: OwnershipFacet, IERC173
141+
OwnershipFacet:
142+
Missing methods:
143+
Mounted selectors:
144+
Selector: 0x8da5cb5b, Function: owner
145+
Selector: 0xf2fde38b, Function: transferOwnership
146+
IERC173:
147+
Missing methods:
148+
Mounted selectors:
149+
Selector: 0x8da5cb5b, Function: owner
150+
Selector: 0xf2fde38b, Function: transferOwnership
151+
- - -
152+
Facet at address: 0xaA91032E567fD3CF2e7102f65B1AaF21530583a0
153+
Possible contracts: TerminusFacet
154+
TerminusFacet:
155+
Missing methods:
156+
Missing selector: 0x01ffc9a7, Function: supportsInterface
157+
Mounted selectors:
158+
Selector: 0x85bc82e2, Function: approveForPool
159+
Selector: 0x00fdd58e, Function: balanceOf
160+
Selector: 0x4e1273f4, Function: balanceOfBatch
161+
Selector: 0xf5298aca, Function: burn
162+
Selector: 0xe8a3d485, Function: contractURI
163+
Selector: 0x3bad2d82, Function: createPoolV1
164+
Selector: 0xb507ef52, Function: createSimplePool
165+
Selector: 0xe985e9c5, Function: isApprovedForAll
166+
Selector: 0x027b3fc2, Function: isApprovedForPool
167+
Selector: 0x731133e9, Function: mint
168+
Selector: 0x1f7fdffa, Function: mintBatch
169+
Selector: 0x3013ce29, Function: paymentToken
170+
Selector: 0x8925d013, Function: poolBasePrice
171+
Selector: 0x21adca96, Function: poolMintBatch
172+
Selector: 0x2eb2c2d6, Function: safeBatchTransferFrom
173+
Selector: 0xf242432a, Function: safeTransferFrom
174+
Selector: 0xa22cb465, Function: setApprovalForAll
175+
Selector: 0x938e3d7b, Function: setContractURI
176+
Selector: 0x92eefe9b, Function: setController
177+
Selector: 0x6a326ab1, Function: setPaymentToken
178+
Selector: 0x78cf2e84, Function: setPoolBasePrice
179+
Selector: 0xdc55d0b2, Function: setPoolController
180+
Selector: 0x862440e2, Function: setURI
181+
Selector: 0x366e59e3, Function: terminusController
182+
Selector: 0x5dc8bdf8, Function: terminusPoolCapacity
183+
Selector: 0xd0c402e5, Function: terminusPoolController
184+
Selector: 0xa44cfc82, Function: terminusPoolSupply
185+
Selector: 0xab3c7e52, Function: totalPools
186+
Selector: 0x0e89341c, Function: uri
187+
Selector: 0x0e7afec5, Function: withdrawPayments
188+
```

operations/templates/terminus-update.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ The Terminus contract is deployed as an EIP2535 Diamond proxy contract with a Te
44

55
This checklist describes how to update the `TerminusFacet` on the Terminus diamond contract.
66

7+
## Purpose of update
8+
9+
Describe what the purpose of this update is.
10+
711
## Deployed addresses
812

913
You will modify this section as you go through the checklist

0 commit comments

Comments
 (0)