Skip to content

Commit ce45931

Browse files
authored
Merge pull request #379 from rhinestonewtf/fix/startale-deposit-bug
fix: starttale account getDeployArgs and getAddress
2 parents c184427 + 1389f26 commit ce45931

3 files changed

Lines changed: 102 additions & 15 deletions

File tree

.changeset/twenty-bananas-yell.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@rhinestone/sdk": patch
3+
---
4+
5+
Fix startale getDeployArgs and getAddress

src/accounts/startale.test.ts

Lines changed: 60 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,7 @@ const MOCK_MODULE_ADDRESS = '0x28de6501fa86f2e6cd0b33c3aabdaeb4a1b93f3f'
1515
describe('Accounts: Startale', () => {
1616
describe('Deploy Args', () => {
1717
test('ECDSA owners', () => {
18-
const {
19-
factory,
20-
factoryData,
21-
salt,
22-
implementation,
23-
initializationCallData,
24-
} = getDeployArgs({
18+
const result = getDeployArgs({
2519
account: {
2620
type: 'startale',
2721
},
@@ -30,6 +24,14 @@ describe('Accounts: Startale', () => {
3024
accounts: [accountA, accountB],
3125
},
3226
})
27+
expect(result).not.toBeNull()
28+
const {
29+
factory,
30+
factoryData,
31+
salt,
32+
implementation,
33+
initializationCallData,
34+
} = result!
3335

3436
expect(factory).toEqual('0x0000003b3e7b530b4f981ae80d9350392defef90')
3537
expect(factoryData).toEqual(
@@ -47,13 +49,7 @@ describe('Accounts: Startale', () => {
4749
})
4850

4951
test('Passkey owner', () => {
50-
const {
51-
factory,
52-
factoryData,
53-
salt,
54-
implementation,
55-
initializationCallData,
56-
} = getDeployArgs({
52+
const result = getDeployArgs({
5753
account: {
5854
type: 'startale',
5955
},
@@ -62,6 +58,14 @@ describe('Accounts: Startale', () => {
6258
accounts: [passkeyAccount],
6359
},
6460
})
61+
expect(result).not.toBeNull()
62+
const {
63+
factory,
64+
factoryData,
65+
salt,
66+
implementation,
67+
initializationCallData,
68+
} = result!
6569

6670
expect(factory).toEqual('0x0000003b3e7b530b4f981ae80d9350392defef90')
6771
expect(factoryData).toEqual(
@@ -106,6 +110,48 @@ describe('Accounts: Startale', () => {
106110

107111
expect(address).toEqual('0x4d78f6b273d07f2fd24433ebc7a90d89f0d061ae')
108112
})
113+
114+
test('initData with address fallback', () => {
115+
const expectedAddress = '0x229ca553b9863b0c8f2f03d4287cb8c73e2bede7'
116+
const address = getAddress({
117+
account: {
118+
type: 'startale',
119+
},
120+
owners: {
121+
type: 'ecdsa',
122+
accounts: [accountA],
123+
},
124+
initData: {
125+
address: expectedAddress,
126+
},
127+
})
128+
expect(address).toEqual(expectedAddress)
129+
})
130+
131+
test('initData with factory decodes correctly', () => {
132+
// First get the real deploy args to get valid factory/factoryData
133+
const deployArgs = getDeployArgs({
134+
account: { type: 'startale' },
135+
owners: { type: 'ecdsa', accounts: [accountA, accountB] },
136+
})
137+
expect(deployArgs).not.toBeNull()
138+
const { factory, factoryData } = deployArgs!
139+
140+
// Now use initData path with a different owners set (simulating mock signer)
141+
const address = getAddress({
142+
account: { type: 'startale' },
143+
owners: { type: 'ecdsa', accounts: [accountA] },
144+
initData: {
145+
address: '0x614ea8885429c480a83deddd2e050d411da36d4b',
146+
factory,
147+
factoryData,
148+
intentExecutorInstalled: true,
149+
},
150+
})
151+
152+
// Should derive the same address from factoryData, not from the mock owners
153+
expect(address).toEqual('0x614ea8885429c480a83deddd2e050d411da36d4b')
154+
})
109155
})
110156

111157
describe('Get Install Data', () => {

src/accounts/startale.ts

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { Address, Chain, Hex, PublicClient } from 'viem'
22
import {
33
concat,
4+
decodeFunctionData,
45
encodeAbiParameters,
56
encodeFunctionData,
67
encodePacked,
@@ -39,6 +40,34 @@ const CREATION_CODE =
3940
'0x608060405261029d803803806100148161018c565b92833981016040828203126101885781516001600160a01b03811692909190838303610188576020810151906001600160401b03821161018857019281601f8501121561018857835161006e610069826101c5565b61018c565b9481865260208601936020838301011161018857815f926020809301865e8601015260017f754fd8b321c4649cb777ae6fdce7e89e9cceaa31a4f639795c7807eb7f1a27005d823b15610176577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b031916821790557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a282511561015e575f8091610146945190845af43d15610156573d91610137610069846101c5565b9283523d5f602085013e6101e0565b505b604051605e908161023f8239f35b6060916101e0565b50505034156101485763b398979f60e01b5f5260045ffd5b634c9c8ce360e01b5f5260045260245ffd5b5f80fd5b6040519190601f01601f191682016001600160401b038111838210176101b157604052565b634e487b7160e01b5f52604160045260245ffd5b6001600160401b0381116101b157601f01601f191660200190565b9061020457508051156101f557805190602001fd5b63d6bda27560e01b5f5260045ffd5b81511580610235575b610215575090565b639996b31560e01b5f9081526001600160a01b0391909116600452602490fd5b50803b1561020d56fe60806040523615605c575f8073ffffffffffffffffffffffffffffffffffffffff7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5416368280378136915af43d5f803e156058573d5ff35b3d5ffd5b00'
4041

4142
function getDeployArgs(config: RhinestoneAccountConfig) {
43+
if (config.initData) {
44+
if (!('factory' in config.initData)) {
45+
return null
46+
}
47+
const { factory, factoryData } = config.initData
48+
try {
49+
const decoded = decodeFunctionData({
50+
abi: parseAbi(['function createAccount(bytes,bytes32)']),
51+
data: factoryData,
52+
})
53+
const initData = decoded.args[0]
54+
const salt = decoded.args[1]
55+
const initializationCallData = encodeFunctionData({
56+
abi: parseAbi(['function initializeAccount(bytes)']),
57+
functionName: 'initializeAccount',
58+
args: [initData],
59+
})
60+
return {
61+
factory,
62+
factoryData,
63+
salt,
64+
implementation: IMPLEMENTATION_ADDRESS,
65+
initializationCallData,
66+
}
67+
} catch {
68+
return null
69+
}
70+
}
4271
const account = config.account
4372
const salt = (account as StartaleAccount)?.salt ?? zeroHash
4473
const moduleSetup = getModuleSetup(config)
@@ -97,7 +126,14 @@ function getDeployArgs(config: RhinestoneAccountConfig) {
97126
}
98127

99128
function getAddress(config: RhinestoneAccountConfig) {
100-
const { factory, salt, initializationCallData } = getDeployArgs(config)
129+
const deployArgs = getDeployArgs(config)
130+
if (!deployArgs) {
131+
if (config.initData?.address) {
132+
return config.initData.address
133+
}
134+
throw new Error('Cannot derive address: deploy args not available')
135+
}
136+
const { factory, salt, initializationCallData } = deployArgs
101137

102138
const accountInitData = encodeAbiParameters(
103139
[

0 commit comments

Comments
 (0)