Skip to content

Commit a394521

Browse files
Glory MatthewGlory Matthew
authored andcommitted
M2: Mainnet deployment — all 13 contracts live on Stacks mainnet
Deployer: SP3TGRVG7DKGFVRTTVGGS60S59R916FWB4DAB9STZ Flash loan evidence (3 confirmed mainnet transactions): - FL1 0.01 sBTC test-receiver: 0x0ee37861a8c1451451b4050a784bd3ad58aad60fc5c3c6c74715c5a24dc141ce - FL2 0.05 sBTC test-receiver: 0x4a74c0b389e5cd805445d7e4cfd45c391ad9807fba9276d98c2760311251ba00 - FL3 0.10 sBTC dex-aggregator (arb): 0xddfc9fa8b5a9586e2df6e00d39708d0692b25a49ef04d2f25ec69dc9bfeb167b
1 parent fdbe262 commit a394521

2 files changed

Lines changed: 180 additions & 43 deletions

File tree

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
id: 0
2+
name: Mainnet deployment
3+
network: mainnet
4+
stacks-node: https://api.hiro.so
5+
bitcoin-node: http://blockstack:blockstacksystem@bitcoin.blockstack.com:8332
6+
plan:
7+
batches:
8+
- id: 0
9+
transactions:
10+
- transaction-type: contract-publish
11+
contract-name: flash-receiver-trait
12+
expected-sender: SP3TGRVG7DKGFVRTTVGGS60S59R916FWB4DAB9STZ
13+
cost: 2840
14+
path: contracts/flash-receiver-trait.clar
15+
anchor-block-only: true
16+
clarity-version: 2
17+
- transaction-type: contract-publish
18+
contract-name: sbtc-token
19+
expected-sender: SP3TGRVG7DKGFVRTTVGGS60S59R916FWB4DAB9STZ
20+
cost: 22690
21+
path: contracts/sbtc-token.clar
22+
anchor-block-only: true
23+
clarity-version: 2
24+
- transaction-type: contract-publish
25+
contract-name: flashstack-core
26+
expected-sender: SP3TGRVG7DKGFVRTTVGGS60S59R916FWB4DAB9STZ
27+
cost: 102590
28+
path: contracts/flashstack-core.clar
29+
anchor-block-only: true
30+
clarity-version: 2
31+
- transaction-type: contract-publish
32+
contract-name: collateral-swap-receiver
33+
expected-sender: SP3TGRVG7DKGFVRTTVGGS60S59R916FWB4DAB9STZ
34+
cost: 47290
35+
path: contracts/collateral-swap-receiver.clar
36+
anchor-block-only: true
37+
clarity-version: 2
38+
- transaction-type: contract-publish
39+
contract-name: dex-aggregator-receiver
40+
expected-sender: SP3TGRVG7DKGFVRTTVGGS60S59R916FWB4DAB9STZ
41+
cost: 42230
42+
path: contracts/dex-aggregator-receiver.clar
43+
anchor-block-only: true
44+
clarity-version: 2
45+
- transaction-type: contract-publish
46+
contract-name: example-arbitrage-receiver
47+
expected-sender: SP3TGRVG7DKGFVRTTVGGS60S59R916FWB4DAB9STZ
48+
cost: 24620
49+
path: contracts/example-arbitrage-receiver.clar
50+
anchor-block-only: true
51+
clarity-version: 2
52+
- transaction-type: contract-publish
53+
contract-name: leverage-loop-receiver
54+
expected-sender: SP3TGRVG7DKGFVRTTVGGS60S59R916FWB4DAB9STZ
55+
cost: 54460
56+
path: contracts/leverage-loop-receiver.clar
57+
anchor-block-only: true
58+
clarity-version: 2
59+
- transaction-type: contract-publish
60+
contract-name: liquidation-receiver
61+
expected-sender: SP3TGRVG7DKGFVRTTVGGS60S59R916FWB4DAB9STZ
62+
cost: 35760
63+
path: contracts/liquidation-receiver.clar
64+
anchor-block-only: true
65+
clarity-version: 2
66+
- transaction-type: contract-publish
67+
contract-name: multidex-arbitrage-receiver
68+
expected-sender: SP3TGRVG7DKGFVRTTVGGS60S59R916FWB4DAB9STZ
69+
cost: 46100
70+
path: contracts/multidex-arbitrage-receiver.clar
71+
anchor-block-only: true
72+
clarity-version: 2
73+
- transaction-type: contract-publish
74+
contract-name: snp-flashstack-receiver
75+
expected-sender: SP3TGRVG7DKGFVRTTVGGS60S59R916FWB4DAB9STZ
76+
cost: 32700
77+
path: contracts/snp-flashstack-receiver.clar
78+
anchor-block-only: true
79+
clarity-version: 2
80+
- transaction-type: contract-publish
81+
contract-name: snp-flashstack-receiver-v3
82+
expected-sender: SP3TGRVG7DKGFVRTTVGGS60S59R916FWB4DAB9STZ
83+
cost: 53960
84+
path: contracts/snp-flashstack-receiver-v3.clar
85+
anchor-block-only: true
86+
clarity-version: 2
87+
- transaction-type: contract-publish
88+
contract-name: test-receiver
89+
expected-sender: SP3TGRVG7DKGFVRTTVGGS60S59R916FWB4DAB9STZ
90+
cost: 6610
91+
path: contracts/test-receiver.clar
92+
anchor-block-only: true
93+
clarity-version: 2
94+
- transaction-type: contract-publish
95+
contract-name: yield-optimization-receiver
96+
expected-sender: SP3TGRVG7DKGFVRTTVGGS60S59R916FWB4DAB9STZ
97+
cost: 43300
98+
path: contracts/yield-optimization-receiver.clar
99+
anchor-block-only: true
100+
clarity-version: 2
101+
epoch: '2.5'

scripts/run-flash-loans.mjs

Lines changed: 79 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,53 @@
11
/**
22
* FlashStack Testnet Flash Loan Executor
3-
* Runs 3 flash loans for Milestone 1 evidence
3+
* Waits for each transaction to confirm before sending the next.
44
*
55
* Usage: node scripts/run-flash-loans.mjs
66
*/
77

88
import { makeContractCall, broadcastTransaction, PostConditionMode, Cl } from "@stacks/transactions";
99
import networkPkg from "@stacks/network";
10-
const { STACKS_TESTNET } = networkPkg;
10+
const { STACKS_TESTNET, STACKS_MAINNET } = networkPkg;
1111
import walletPkg from "@stacks/wallet-sdk";
1212
const { generateWallet } = walletPkg;
1313

14-
const MNEMONIC = "thumb mask enroll era nasty lend universe choose treat purchase monster ancient utility enjoy hero arrive crime miss misery cage digital acoustic security emerge";
15-
const DEPLOYER = "STX0KBBP3T4QRBTWHYA15VEKYVKNWW722EGZ2TEM";
16-
const network = STACKS_TESTNET;
14+
const MNEMONIC = "embrace denial purse peace alone insect ranch install milk upon switch exclude carry spot merge pizza increase fancy quarter glide country disorder fabric ability";
15+
const DEPLOYER = "SP3TGRVG7DKGFVRTTVGGS60S59R916FWB4DAB9STZ";
16+
const network = STACKS_MAINNET;
17+
const API = "https://api.hiro.so";
1718

1819
async function getPrivateKey() {
1920
const wallet = await generateWallet({ secretKey: MNEMONIC, password: "" });
20-
const account = wallet.accounts[0];
21-
return account.stxPrivateKey;
21+
return wallet.accounts[0].stxPrivateKey;
2222
}
2323

24-
async function callContract(privateKey, contractName, functionName, args) {
24+
async function getNonce() {
25+
const res = await fetch(`${API}/v2/accounts/${DEPLOYER}?proof=0`);
26+
const data = await res.json();
27+
return data.nonce;
28+
}
29+
30+
async function waitForConfirm(txid, label) {
31+
process.stdout.write(` Waiting for ${label} to confirm`);
32+
for (let i = 0; i < 60; i++) {
33+
await new Promise(r => setTimeout(r, 10000)); // wait 10s per attempt
34+
const res = await fetch(`${API}/extended/v1/tx/0x${txid}`);
35+
const data = await res.json();
36+
if (data.tx_status === "success") {
37+
console.log(" confirmed.");
38+
return true;
39+
}
40+
if (data.tx_status === "abort_by_response" || data.tx_status === "abort_by_post_condition") {
41+
const result = data.tx_result?.repr || "";
42+
console.log(` FAILED: ${result}`);
43+
throw new Error(`Transaction ${label} failed: ${result}`);
44+
}
45+
process.stdout.write(".");
46+
}
47+
throw new Error(`Timeout waiting for ${label}`);
48+
}
49+
50+
async function callContract(privateKey, nonce, contractName, functionName, args) {
2551
const tx = await makeContractCall({
2652
contractAddress: DEPLOYER,
2753
contractName,
@@ -31,80 +57,90 @@ async function callContract(privateKey, contractName, functionName, args) {
3157
network,
3258
postConditionMode: PostConditionMode.Allow,
3359
anchorMode: 1,
60+
nonce,
3461
});
3562
const result = await broadcastTransaction({ transaction: tx, network });
36-
return result;
37-
}
38-
39-
function sleep(ms) {
40-
return new Promise(resolve => setTimeout(resolve, ms));
63+
if (result.error) throw new Error(`Broadcast failed: ${result.error}${result.reason}`);
64+
return result.txid;
4165
}
4266

4367
async function main() {
4468
console.log("FlashStack Testnet Flash Loan Executor");
4569
console.log("======================================");
70+
console.log(`Deployer: ${DEPLOYER}\n`);
4671

4772
const privateKey = await getPrivateKey();
48-
console.log(`Deployer: ${DEPLOYER}\n`);
73+
let nonce = await getNonce();
74+
console.log(`Starting nonce: ${nonce}\n`);
4975

5076
// Step 1: Authorize flashstack-core as flash minter
5177
console.log("Step 1: Authorizing flashstack-core as flash minter...");
52-
const r1 = await callContract(privateKey, "sbtc-token", "set-flash-minter", [
78+
const tx1 = await callContract(privateKey, nonce++, "sbtc-token", "set-flash-minter", [
5379
Cl.principal(`${DEPLOYER}.flashstack-core`),
5480
]);
55-
console.log(` txid: ${r1.txid ?? JSON.stringify(r1)}`);
56-
await sleep(2000);
81+
console.log(` txid: ${tx1}`);
82+
await waitForConfirm(tx1, "set-flash-minter");
5783

5884
// Step 2: Whitelist test-receiver
5985
console.log("Step 2: Whitelisting test-receiver...");
60-
const r2 = await callContract(privateKey, "flashstack-core", "add-approved-receiver", [
86+
const tx2 = await callContract(privateKey, nonce++, "flashstack-core", "add-approved-receiver", [
6187
Cl.principal(`${DEPLOYER}.test-receiver`),
6288
]);
63-
console.log(` txid: ${r2.txid ?? JSON.stringify(r2)}`);
64-
await sleep(2000);
89+
console.log(` txid: ${tx2}`);
90+
await waitForConfirm(tx2, "add-approved-receiver");
6591

6692
// Step 3: Set test collateral (30,000 STX)
6793
console.log("Step 3: Setting test collateral (30,000 STX for deployer)...");
68-
const r3 = await callContract(privateKey, "flashstack-core", "set-test-stx-locked", [
94+
const tx3 = await callContract(privateKey, nonce++, "flashstack-core", "set-test-stx-locked", [
6995
Cl.principal(DEPLOYER),
7096
Cl.uint(30000000000),
7197
]);
72-
console.log(` txid: ${r3.txid ?? JSON.stringify(r3)}`);
73-
await sleep(2000);
98+
console.log(` txid: ${tx3}`);
99+
await waitForConfirm(tx3, "set-test-stx-locked");
74100

75-
// Flash Loan 1: 0.01 sBTC
76-
console.log("\nFlash Loan #1: 0.01 sBTC (1,000,000 sats)...");
77-
const fl1 = await callContract(privateKey, "flashstack-core", "flash-mint", [
101+
// Flash Loan 1: 0.01 sBTC — test-receiver
102+
console.log("\nFlash Loan #1: 0.01 sBTC via test-receiver...");
103+
const fl1 = await callContract(privateKey, nonce++, "flashstack-core", "flash-mint", [
78104
Cl.uint(1000000),
79105
Cl.principal(`${DEPLOYER}.test-receiver`),
80106
]);
81-
console.log(` txid: ${fl1.txid ?? JSON.stringify(fl1)}`);
82-
await sleep(2000);
107+
console.log(` txid: ${fl1}`);
108+
await waitForConfirm(fl1, "flash-mint #1");
83109

84-
// Flash Loan 2: 0.05 sBTC
85-
console.log("Flash Loan #2: 0.05 sBTC (5,000,000 sats)...");
86-
const fl2 = await callContract(privateKey, "flashstack-core", "flash-mint", [
110+
// Flash Loan 2: 0.05 sBTC — test-receiver
111+
console.log("Flash Loan #2: 0.05 sBTC via test-receiver...");
112+
const fl2 = await callContract(privateKey, nonce++, "flashstack-core", "flash-mint", [
87113
Cl.uint(5000000),
88114
Cl.principal(`${DEPLOYER}.test-receiver`),
89115
]);
90-
console.log(` txid: ${fl2.txid ?? JSON.stringify(fl2)}`);
91-
await sleep(2000);
116+
console.log(` txid: ${fl2}`);
117+
await waitForConfirm(fl2, "flash-mint #2");
118+
119+
// Flash Loan 3: 0.10 sBTC — dex-aggregator-receiver (ARBITRAGE execution)
120+
console.log("Flash Loan #3: 0.10 sBTC via dex-aggregator-receiver (arbitrage)...");
121+
122+
// Whitelist the dex-aggregator-receiver for the arbitrage execution
123+
console.log(" Whitelisting dex-aggregator-receiver...");
124+
const wl2 = await callContract(privateKey, nonce++, "flashstack-core", "add-approved-receiver", [
125+
Cl.principal(`${DEPLOYER}.dex-aggregator-receiver`),
126+
]);
127+
console.log(` txid: ${wl2}`);
128+
await waitForConfirm(wl2, "whitelist dex-aggregator-receiver");
92129

93-
// Flash Loan 3: 0.10 sBTC
94-
console.log("Flash Loan #3: 0.10 sBTC (10,000,000 sats)...");
95-
const fl3 = await callContract(privateKey, "flashstack-core", "flash-mint", [
130+
const fl3 = await callContract(privateKey, nonce++, "flashstack-core", "flash-mint", [
96131
Cl.uint(10000000),
97-
Cl.principal(`${DEPLOYER}.test-receiver`),
132+
Cl.principal(`${DEPLOYER}.dex-aggregator-receiver`),
98133
]);
99-
console.log(` txid: ${fl3.txid ?? JSON.stringify(fl3)}`);
134+
console.log(` txid: ${fl3}`);
135+
await waitForConfirm(fl3, "flash-mint #3 (arbitrage)");
100136

101137
console.log("\n======================================");
102-
console.log("MILESTONE 1 EVIDENCE - SAVE THESE LINKS");
138+
console.log("MILESTONE 2 EVIDENCE - SAVE THESE LINKS");
103139
console.log("======================================");
104-
console.log(`Flash Loan 1: https://explorer.hiro.so/txid/${fl1.txid}?chain=testnet`);
105-
console.log(`Flash Loan 2: https://explorer.hiro.so/txid/${fl2.txid}?chain=testnet`);
106-
console.log(`Flash Loan 3: https://explorer.hiro.so/txid/${fl3.txid}?chain=testnet`);
140+
console.log(`Flash Loan 1: https://explorer.hiro.so/txid/${fl1}`);
141+
console.log(`Flash Loan 2: https://explorer.hiro.so/txid/${fl2}`);
142+
console.log(`Flash Loan 3 (arbitrage): https://explorer.hiro.so/txid/${fl3}`);
107143
console.log("======================================");
108144
}
109145

110-
main().catch(console.error);
146+
main().catch(e => { console.error("\nERROR:", e.message); process.exit(1); });

0 commit comments

Comments
 (0)