@@ -42,12 +42,39 @@ contract CallPolicy is PolicyBase {
4242
4343 mapping (address => uint256 ) public usedIds;
4444 mapping (bytes32 id = > mapping (address => Status)) public status;
45- mapping (bytes32 id = > mapping (bytes32 permissionHash = > mapping (address => bytes ))) public encodedPermissions;
45+ // mapping(bytes32 id => mapping(bytes32 permissionHash => mapping(address => bytes))) public encodedPermissions;
4646
4747 function isInitialized (address wallet ) external view override returns (bool ) {
4848 return usedIds[wallet] > 0 ;
4949 }
5050
51+ function setPermission (bytes32 _id , bytes32 _permissionHash , address _owner , bytes memory _permission ) internal {
52+ bytes32 slot = keccak256 (bytes .concat (bytes32 (uint256 (uint160 (_owner))), keccak256 (bytes .concat (_id,_permissionHash))));
53+
54+ uint256 length = _permission.length ;
55+ assembly {
56+ // store length on first slot, as usual
57+ sstore (slot, length)
58+ for { let cursor := 0x20 } lt (cursor, add (length, 0x20 )) { cursor := add (cursor, 0x20 ) } {
59+ sstore (add (slot, div (cursor, 0x20 )), mload (add (_permission, cursor))) // slot + cursor/32
60+ }
61+ }
62+ }
63+
64+ function encodedPermissions (bytes32 _id , bytes32 _permissionHash , address _owner ) public view returns (bytes memory encoded ) {
65+ bytes32 slot = keccak256 (bytes .concat (bytes32 (uint256 (uint160 (_owner))), keccak256 (bytes .concat (_id,_permissionHash))));
66+ uint256 length;
67+ assembly {
68+ encoded := mload (0x40 )
69+ length := sload (slot)
70+ mstore (encoded, length)
71+ for { let cursor := 0x20 } lt (cursor, add (length, 0x20 )) { cursor := add (cursor, 0x20 ) } {
72+ mstore (add (encoded, cursor), sload (add (slot, div (cursor, 0x20 ))))
73+ }
74+ mstore (0x40 , add (encoded, add (length, 0x20 )))
75+ }
76+ }
77+
5178 function checkUserOpPolicy (bytes32 id , PackedUserOperation calldata userOp )
5279 external
5380 payable
@@ -100,13 +127,13 @@ contract CallPolicy is PolicyBase {
100127 ) internal returns (bool ) {
101128 bytes4 _data = data.length == 0 ? bytes4 (0x0 ) : bytes4 (data[0 :4 ]);
102129 bytes32 permissionHash = keccak256 (abi.encodePacked (callType, target, _data));
103- bytes memory encodedPermission = encodedPermissions[id][ permissionHash][ wallet] ;
130+ bytes memory encodedPermission = encodedPermissions (id, permissionHash, wallet) ;
104131
105132 // try to find the permission with zero address which means ANY target address
106133 // e.g. allow to call `approve` function of `ANY` ERC20 token contracts
107134 if (encodedPermission.length == 0 ) {
108135 bytes32 permissionHashWithZeroAddress = keccak256 (abi.encodePacked (callType, address (0 ), _data));
109- encodedPermission = encodedPermissions[id][ permissionHashWithZeroAddress][ wallet] ;
136+ encodedPermission = encodedPermissions (id, permissionHashWithZeroAddress, wallet) ;
110137 }
111138
112139 // if still no permission found, then the call is not allowed
@@ -175,7 +202,7 @@ contract CallPolicy is PolicyBase {
175202 // check if the permissionHash is unique
176203 bytes32 permissionHash =
177204 keccak256 (abi.encodePacked (permissions[i].callType, permissions[i].target, permissions[i].selector ));
178- require (encodedPermissions[id][ permissionHash][ msg .sender ] .length == 0 , "duplicate permissionHash " );
205+ require (encodedPermissions (id, permissionHash, msg .sender ) .length == 0 , "duplicate permissionHash " );
179206
180207 // check if the params length is correct
181208 for (uint256 j = 0 ; j < permissions[i].rules.length ; j++ ) {
@@ -184,8 +211,10 @@ contract CallPolicy is PolicyBase {
184211 }
185212 }
186213
187- encodedPermissions[id][permissionHash][msg .sender ] =
188- abi.encode (permissions[i].valueLimit, permissions[i].rules);
214+ setPermission (
215+ id,permissionHash,msg .sender ,
216+ abi.encode (permissions[i].valueLimit, permissions[i].rules)
217+ );
189218 }
190219 status[id][msg .sender ] = Status.Live;
191220 usedIds[msg .sender ]++ ;
0 commit comments