Sitelet https://github.com/roycoprotocol/royco-iam/commit/e1f2fc810cbdc67c9101cc84d14671cbb7a92cca
Skip to content

Commit e1f2fc8

Browse files
committed
better logging for verification script
1 parent dc05190 commit e1f2fc8

1 file changed

Lines changed: 136 additions & 24 deletions

File tree

Lines changed: 136 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// SPDX-Liense-Identifier: AGPL-3.0-only
1+
// SPDX-License-Identifier: AGPL-3.0-only
22
pragma solidity ^0.8.0;
33

44
import { RecipeMarketHub, ERC20, RecipeMarketHubTestBase } from "../utils/RecipeMarketHub/RecipeMarketHubTestBase.sol";
@@ -18,15 +18,24 @@ contract RecipeVerifier is RecipeMarketHubTestBase {
1818
uint256 fork;
1919

2020
function setUp() public {
21-
// Replace this with whatever network the Royco Recipe IAM was created on
21+
// Replace this with the correct network if needed
2222
fork = vm.createFork(MAINNET_RPC_URL);
2323

24+
// Replace with the correct RecipeMarketHub instance
2425
RECIPE_MARKET_HUB = RecipeMarketHub(0x783251f103555068c1E9D755f69458f39eD937c0);
2526

26-
// Replace this with the market hash of the market you are trying to verify
27+
// Replace with the market hash of the market you want to verify
2728
MARKET_HASH = 0x83c459782b2ff36629401b1a592354fc085f29ae00cf97b803f73cac464d389b;
2829
}
2930

31+
function getRoleOrAddress(address candidate, address ap, address wallet, address hub) internal pure returns (string memory) {
32+
if (candidate == ap) return "AP";
33+
if (candidate == wallet) return "WeirollWallet";
34+
if (candidate == hub) return "RecipeMarketHub";
35+
// Return the hex string of the address if not one of the known roles
36+
return _addressToString(candidate);
37+
}
38+
3039
function test_RecipeMarketVerification() external {
3140
vm.selectFork(fork);
3241

@@ -35,15 +44,17 @@ contract RecipeVerifier is RecipeMarketHubTestBase {
3544
// Get the token to deposit for this market
3645
(, ERC20 marketInputToken, uint256 lockupTime,,,,) = RECIPE_MARKET_HUB.marketHashToWeirollMarket(MARKET_HASH);
3746

38-
uint256 offerAmount = 5_000_000 * (10 ** (marketInputToken.decimals()));
39-
uint256 numDepositors = 100;
47+
// Tune this amount for total offer amount
48+
uint256 offerAmount = 10_000 * (10 ** (marketInputToken.decimals()));
49+
// Tune this to simulate this amount of APs filling the offer
50+
uint256 numDepositors = 1;
4051

4152
// Create an IP offer in the market
4253
address[] memory incentives = new address[](0);
4354
uint256[] memory incentiveAmounts = new uint256[](0);
4455
bytes32 ipOfferHash = RECIPE_MARKET_HUB.createIPOffer(MARKET_HASH, offerAmount, 0, incentives, incentiveAmounts);
4556

46-
// Fill the IP Offer
57+
// Fill the IP Offer (Deposit phase)
4758
address[] memory aps = new address[](numDepositors);
4859
uint256[] memory fillAmounts = new uint256[](numDepositors);
4960
address[] memory weirollWallets = new address[](numDepositors);
@@ -52,7 +63,13 @@ contract RecipeVerifier is RecipeMarketHubTestBase {
5263
ipOfferHashes[0] = ipOfferHash;
5364
uint256[] memory depositorFillAmounts = new uint256[](1);
5465

55-
// Distribute fill amounts based on random amounts
66+
console2.log("-----------------------------------------------------");
67+
console2.log("Deposit Recipe Flow:");
68+
console2.log("-----------------------------------------------------");
69+
70+
// -------------------------
71+
// Deposit Phase (Filling the Offer)
72+
// -------------------------
5673
for (uint256 i = 0; i < numDepositors; i++) {
5774
(address ap,) = makeAddrAndKey(string(abi.encode(i)));
5875
aps[i] = ap;
@@ -64,24 +81,64 @@ contract RecipeVerifier is RecipeMarketHubTestBase {
6481
fillAmounts[i] = fillAmount;
6582

6683
// Fund the AP and handle approval
67-
deal(address(marketInputToken), ap, fillAmounts[i]);
84+
deal(address(marketInputToken), ap, fillAmount);
6885
vm.startPrank(ap);
69-
marketInputToken.approve(address(RECIPE_MARKET_HUB), fillAmounts[i]);
86+
marketInputToken.approve(address(RECIPE_MARKET_HUB), fillAmount);
7087

71-
depositorFillAmounts[0] = fillAmounts[i];
72-
// Record the logs to capture Transfer events
88+
depositorFillAmounts[0] = fillAmount;
89+
// Record the logs to capture Transfer events during deposit
7390
vm.recordLogs();
7491
// AP Fills the offer (no funding vault)
7592
RECIPE_MARKET_HUB.fillIPOffers(ipOfferHashes, depositorFillAmounts, address(0), address(0xbeef));
7693
vm.stopPrank();
7794

95+
Vm.Log[] memory depositLogs = vm.getRecordedLogs();
96+
7897
// Extract the Weiroll wallet address
79-
weirollWallets[i] = address(uint160(uint256(vm.getRecordedLogs()[0].topics[2])));
98+
weirollWallets[i] = address(uint160(uint256(depositLogs[0].topics[2])));
99+
100+
// Process each Transfer event log for deposit
101+
for (uint256 j = 0; j < depositLogs.length; j++) {
102+
Vm.Log memory log = depositLogs[j];
103+
104+
if (log.topics[0] == TRANSFER_EVENT_SIG) {
105+
address from = address(uint160(uint256(log.topics[1])));
106+
address to = address(uint160(uint256(log.topics[2])));
107+
uint256 amount = abi.decode(log.data, (uint256));
108+
109+
if (i == 0) {
110+
string memory tokenName;
111+
try ERC20(log.emitter).name() returns (string memory name) {
112+
tokenName = name;
113+
} catch {
114+
tokenName = "<Unknown Token>";
115+
}
116+
117+
// Identify roles or addresses
118+
string memory fromEntity = getRoleOrAddress(from, aps[i], weirollWallets[i], address(RECIPE_MARKET_HUB));
119+
string memory toEntity = getRoleOrAddress(to, aps[i], weirollWallets[i], address(RECIPE_MARKET_HUB));
120+
121+
// Single sentence log for deposit
122+
console2.log(
123+
string(abi.encodePacked(fromEntity, " sent ", _uintToString(amount), " ", tokenName, " to ", toEntity, " during deposit."))
124+
);
125+
}
126+
}
127+
}
80128
}
81129

130+
// -------------------------
131+
// Withdrawal Phase
132+
// -------------------------
133+
82134
// Time travel to when the deposits are withdrawable
83135
vm.warp(block.timestamp + lockupTime);
84136

137+
console2.log("");
138+
console2.log("-----------------------------------------------------");
139+
console2.log("Withdrawal Recipe Flow:");
140+
console2.log("-----------------------------------------------------");
141+
85142
for (uint256 i = 0; i < numDepositors; ++i) {
86143
vm.warp(block.timestamp + (i * 30 minutes));
87144

@@ -92,37 +149,92 @@ contract RecipeVerifier is RecipeMarketHubTestBase {
92149
RECIPE_MARKET_HUB.executeWithdrawalScript(weirollWallets[i]);
93150
vm.stopPrank();
94151

95-
Vm.Log[] memory logs = vm.getRecordedLogs();
152+
Vm.Log[] memory withdrawLogs = vm.getRecordedLogs();
96153

97154
bool apReceivedTokens = false;
98155
bool walletReceivedTokens = false;
99156

100-
for (uint256 j = 0; j < logs.length; j++) {
101-
Vm.Log memory log = logs[j];
157+
// Process each Transfer event log for withdrawal
158+
for (uint256 j = 0; j < withdrawLogs.length; j++) {
159+
Vm.Log memory log = withdrawLogs[j];
102160

103-
// Check if the log matches the Transfer signature and was emitted by the token contract
104161
if (log.topics[0] == TRANSFER_EVENT_SIG) {
162+
address from = address(uint160(uint256(log.topics[1])));
105163
address to = address(uint160(uint256(log.topics[2])));
106-
string memory tokenName = ERC20(log.emitter).name();
107164
uint256 amount = abi.decode(log.data, (uint256));
108165

109-
if (to == aps[i]) {
110-
if (i == 0) {
111-
console2.log("AP received ", amount, " of ", tokenName);
166+
if (i == 0) {
167+
string memory tokenName;
168+
try ERC20(log.emitter).name() returns (string memory name) {
169+
tokenName = name;
170+
} catch {
171+
tokenName = "<Unknown Token>";
112172
}
173+
174+
// Identify roles or addresses
175+
string memory fromEntity = getRoleOrAddress(from, aps[i], weirollWallets[i], address(RECIPE_MARKET_HUB));
176+
string memory toEntity = getRoleOrAddress(to, aps[i], weirollWallets[i], address(RECIPE_MARKET_HUB));
177+
178+
// Single sentence log for withdrawal
179+
console2.log(
180+
string(abi.encodePacked(fromEntity, " sent ", _uintToString(amount), " ", tokenName, " to ", toEntity, " during withdrawal."))
181+
);
182+
}
183+
184+
if (to == aps[i]) {
113185
apReceivedTokens = true;
114186
} else if (to == weirollWallets[i]) {
115-
if (i == 0) {
116-
console2.log("Weiroll Wallet received ", amount, " of ", tokenName);
117-
}
118187
walletReceivedTokens = true;
119188
}
120189
}
121190
}
122191

192+
// Ensure tokens ended up in either the AP or the Weiroll wallet
123193
assert(apReceivedTokens || walletReceivedTokens);
124194
}
125-
195+
console2.log("-----------------------------------------------------");
126196
console2.log("Market Successfully Verified.");
127197
}
198+
199+
// Utility function to convert uint to string
200+
function _uintToString(uint256 v) internal pure returns (string memory) {
201+
if (v == 0) {
202+
return "0";
203+
}
204+
uint256 j = v;
205+
uint256 length;
206+
while (j != 0) {
207+
length++;
208+
j /= 10;
209+
}
210+
bytes memory bstr = new bytes(length);
211+
uint256 k = length;
212+
j = v;
213+
while (j != 0) {
214+
k = k - 1;
215+
uint8 temp = uint8(48 + (j % 10));
216+
bstr[k] = bytes1(temp);
217+
j /= 10;
218+
}
219+
return string(bstr);
220+
}
221+
222+
function _addressToString(address x) internal pure returns (string memory) {
223+
bytes memory s = new bytes(42);
224+
s[0] = "0";
225+
s[1] = "x";
226+
for (uint256 i = 0; i < 20; i++) {
227+
bytes1 b = bytes1(uint8(uint256(uint160(x)) / (2 ** (8 * (19 - i)))));
228+
bytes1 hi = bytes1(uint8(b) / 16);
229+
bytes1 lo = bytes1(uint8(b) - 16 * uint8(hi));
230+
s[2 + 2 * i] = _char(hi);
231+
s[3 + 2 * i] = _char(lo);
232+
}
233+
return string(s);
234+
}
235+
236+
function _char(bytes1 b) internal pure returns (bytes1 c) {
237+
if (uint8(b) < 10) return bytes1(uint8(b) + 0x30);
238+
else return bytes1(uint8(b) + 0x57);
239+
}
128240
}

0 commit comments

Comments
 (0)