@@ -17,30 +17,28 @@ const { FORK_NETWORK_NAME } = process.env;
1717
1818const multsigInfo : MultisigInfo = multsigInfoJson ;
1919
20- describe ( "Should change LBC owner to the multisig" , function ( ) {
20+ describe ( "Should change LBC owner to the multisig.ts " , function ( ) {
2121 it ( "Should change the owner" , async ( ) => {
2222 await checkForkedNetwork ( ) ;
23-
2423 const networkName = FORK_NETWORK_NAME ?? "rskTestnet" ;
24+ console . log ( "Network name:" , networkName ) ;
2525
26+ const lbcName = "LiquidityBridgeContract" ;
2627 const addresses : Partial < DeploymentConfig > = read ( ) ;
2728 const networkDeployments : Partial < DeploymentConfig [ string ] > | undefined =
2829 addresses [ networkName ] ;
29-
3030 const lbcAddress = networkDeployments ?. LiquidityBridgeContract ?. address ;
31+ const safeAddress = multsigInfo [ networkName ] . address ;
3132
3233 if ( ! lbcAddress ) {
3334 throw new Error (
3435 "LiquidityBridgeContract proxy deployment info not found"
3536 ) ;
3637 }
38+ console . info ( `LBC address: ${ lbcAddress } ` ) ;
39+ console . info ( `Safe address: ${ safeAddress } ` ) ;
3740
38- const lbc = await ethers . getContractAt (
39- "LiquidityBridgeContractV2" ,
40- lbcAddress
41- ) ;
42-
43- const safeAddress = multsigInfo [ networkName ] . address ;
41+ const lbc = await ethers . getContractAt ( lbcName , lbcAddress ) ;
4442
4543 const lbcOwner = await lbc . owner ( ) ;
4644 console . info ( "LBC owner:" , lbcOwner ) ;
@@ -52,6 +50,17 @@ describe("Should change LBC owner to the multisig", function () {
5250 ) . to . not . be . reverted ;
5351 const newLbcOwner = await lbc . owner ( ) ;
5452 console . info ( "New LBC owner:" , newLbcOwner ) ;
53+
54+ await expect (
55+ lbc . connect ( impersonatedSigner ) . setProviderStatus ( 1 , false )
56+ ) . to . be . revertedWith ( "LBC005" ) ;
57+
58+ expect (
59+ multisigExecProviderStatusChangeTransaction ( safeAddress , lbcAddress )
60+ ) . to . eventually . be . equal ( true ) ;
61+ expect (
62+ multisigExecUpgradeTransaction ( safeAddress , lbcAddress )
63+ ) . to . eventually . be . equal ( true ) ;
5564 } ) ;
5665} ) ;
5766
@@ -62,3 +71,229 @@ async function checkForkedNetwork() {
6271 console . error ( "Not a forked network:" , error ) ;
6372 }
6473}
74+
75+ function generateConcatenatedSignatures ( owners : string [ ] ) {
76+ const concatenatedSignatures =
77+ "0x" +
78+ owners
79+ . sort ( ( a , b ) => a . toLowerCase ( ) . localeCompare ( b . toLowerCase ( ) ) ) // SORT owners in ascending order
80+ . map ( ( owner ) => {
81+ return "0" . repeat ( 24 ) + owner . slice ( 2 ) + "0" . repeat ( 64 ) + "01" ;
82+ } )
83+ . join ( "" ) ;
84+
85+ return concatenatedSignatures ;
86+ }
87+
88+ export async function multisigExecProviderStatusChangeTransaction (
89+ safeAddress : string ,
90+ lbcAddress : string
91+ ) : Promise < boolean > {
92+ const safeContract = await ethers . getContractAt ( "GnosisSafe" , safeAddress ) ;
93+
94+ const EncoderFactory = await ethers . getContractFactory ( "Encoder" ) ;
95+ const encoderDeployed = await EncoderFactory . deploy ( ) ;
96+ const encoder = await ethers . getContractAt (
97+ "Encoder" ,
98+ await encoderDeployed . getAddress ( )
99+ ) ;
100+
101+ const callData = await encoder . getCallDataSetProviderStatus ( 1 , false ) ;
102+ console . info ( "Call data:" , callData ) ;
103+
104+ const nonce = await safeContract . nonce ( ) ;
105+ console . info ( "Nonce:" , nonce ) ;
106+
107+ const txData = {
108+ to : lbcAddress ,
109+ value : 0 ,
110+ data : callData ,
111+ operation : 0 ,
112+ safeTxGas : 0 ,
113+ baseGas : 0 ,
114+ gasPrice : 0 ,
115+ gasToken : ethers . ZeroAddress ,
116+ refundReceiver : ethers . ZeroAddress ,
117+ nonce : nonce ,
118+ signatures : "0x" ,
119+ } ;
120+
121+ const owners = await safeContract . getOwners ( ) ;
122+
123+ const desiredBalance = ethers . toQuantity ( ethers . parseEther ( "100" ) ) ;
124+
125+ await helpers . impersonateAccount ( owners [ 0 ] ) ;
126+ const impersonateOwner1 = await ethers . getSigner ( owners [ 0 ] ) ;
127+ await ethers . provider . send ( "hardhat_setBalance" , [
128+ impersonateOwner1 . address ,
129+ desiredBalance ,
130+ ] ) ;
131+ await helpers . impersonateAccount ( owners [ 1 ] ) ;
132+ const impersonateOwner2 = await ethers . getSigner ( owners [ 1 ] ) ;
133+ await ethers . provider . send ( "hardhat_setBalance" , [
134+ impersonateOwner2 . address ,
135+ desiredBalance ,
136+ ] ) ;
137+ await helpers . impersonateAccount ( owners [ 2 ] ) ;
138+ const impersonateOwner3 = await ethers . getSigner ( owners [ 2 ] ) ;
139+ await ethers . provider . send ( "hardhat_setBalance" , [
140+ impersonateOwner3 . address ,
141+ desiredBalance ,
142+ ] ) ;
143+
144+ const transactionHash = await safeContract
145+ . connect ( impersonateOwner1 )
146+ . getTransactionHash (
147+ txData . to ,
148+ txData . value ,
149+ txData . data ,
150+ txData . operation ,
151+ txData . safeTxGas ,
152+ txData . baseGas ,
153+ txData . gasPrice ,
154+ txData . gasToken ,
155+ txData . refundReceiver ,
156+ txData . nonce
157+ ) ;
158+ console . info ( "Transaction hash:" , transactionHash ) ;
159+
160+ await safeContract . connect ( impersonateOwner1 ) . approveHash ( transactionHash ) ;
161+ await safeContract . connect ( impersonateOwner2 ) . approveHash ( transactionHash ) ;
162+ await safeContract . connect ( impersonateOwner3 ) . approveHash ( transactionHash ) ;
163+ const signature = generateConcatenatedSignatures ( [
164+ impersonateOwner1 . address ,
165+ impersonateOwner2 . address ,
166+ impersonateOwner3 . address ,
167+ ] ) ;
168+ console . info ( "Signature:" , signature ) ;
169+
170+ txData . signatures = signature ;
171+
172+ const result = await safeContract . execTransaction (
173+ txData . to ,
174+ txData . value ,
175+ txData . data ,
176+ txData . operation ,
177+ txData . safeTxGas ,
178+ txData . baseGas ,
179+ txData . gasPrice ,
180+ txData . gasToken ,
181+ txData . refundReceiver ,
182+ txData . signatures
183+ ) ;
184+
185+ return Boolean ( result ) ;
186+ }
187+
188+ export async function multisigExecUpgradeTransaction (
189+ safeAddress : string ,
190+ lbcAddress : string
191+ ) : Promise < boolean > {
192+ const safeContract = await ethers . getContractAt ( "GnosisSafe" , safeAddress ) ;
193+
194+ const EncoderFactory = await ethers . getContractFactory ( "Encoder" ) ;
195+ const encoderDeployed = await EncoderFactory . deploy ( ) ;
196+ const encoder = await ethers . getContractAt (
197+ "Encoder" ,
198+ await encoderDeployed . getAddress ( )
199+ ) ;
200+
201+ const NewLbcFactory = await ethers . getContractFactory (
202+ "LiquidityBridgeContractV2"
203+ ) ;
204+ const newLbcDeplolyed = await NewLbcFactory . deploy ( ) ;
205+ const newLbc = await ethers . getContractAt (
206+ "LiquidityBridgeContractV2" ,
207+ await newLbcDeplolyed . getAddress ( )
208+ ) ;
209+ const newLbcAddress = await newLbc . getAddress ( ) ;
210+
211+ const callData = await encoder . getCallDataForUpgrade (
212+ lbcAddress ,
213+ newLbcAddress
214+ ) ;
215+ console . info ( "Call data:" , callData ) ;
216+
217+ const nonce = await safeContract . nonce ( ) ;
218+ console . info ( "Nonce:" , nonce ) ;
219+
220+ const txData = {
221+ to : lbcAddress ,
222+ value : 0 ,
223+ data : callData ,
224+ operation : 0 ,
225+ safeTxGas : 0 ,
226+ baseGas : 0 ,
227+ gasPrice : 0 ,
228+ gasToken : ethers . ZeroAddress ,
229+ refundReceiver : ethers . ZeroAddress ,
230+ nonce : nonce ,
231+ signatures : "0x" ,
232+ } ;
233+
234+ const owners = await safeContract . getOwners ( ) ;
235+
236+ const desiredBalance = ethers . toQuantity ( ethers . parseEther ( "100" ) ) ;
237+
238+ await helpers . impersonateAccount ( owners [ 0 ] ) ;
239+ const impersonateOwner1 = await ethers . getSigner ( owners [ 0 ] ) ;
240+ await ethers . provider . send ( "hardhat_setBalance" , [
241+ impersonateOwner1 . address ,
242+ desiredBalance ,
243+ ] ) ;
244+ await helpers . impersonateAccount ( owners [ 1 ] ) ;
245+ const impersonateOwner2 = await ethers . getSigner ( owners [ 1 ] ) ;
246+ await ethers . provider . send ( "hardhat_setBalance" , [
247+ impersonateOwner2 . address ,
248+ desiredBalance ,
249+ ] ) ;
250+ await helpers . impersonateAccount ( owners [ 2 ] ) ;
251+ const impersonateOwner3 = await ethers . getSigner ( owners [ 2 ] ) ;
252+ await ethers . provider . send ( "hardhat_setBalance" , [
253+ impersonateOwner3 . address ,
254+ desiredBalance ,
255+ ] ) ;
256+
257+ const transactionHash = await safeContract
258+ . connect ( impersonateOwner1 )
259+ . getTransactionHash (
260+ txData . to ,
261+ txData . value ,
262+ txData . data ,
263+ txData . operation ,
264+ txData . safeTxGas ,
265+ txData . baseGas ,
266+ txData . gasPrice ,
267+ txData . gasToken ,
268+ txData . refundReceiver ,
269+ txData . nonce
270+ ) ;
271+ console . info ( "Transaction hash:" , transactionHash ) ;
272+
273+ await safeContract . connect ( impersonateOwner1 ) . approveHash ( transactionHash ) ;
274+ await safeContract . connect ( impersonateOwner2 ) . approveHash ( transactionHash ) ;
275+ await safeContract . connect ( impersonateOwner3 ) . approveHash ( transactionHash ) ;
276+ const signature = generateConcatenatedSignatures ( [
277+ impersonateOwner1 . address ,
278+ impersonateOwner2 . address ,
279+ impersonateOwner3 . address ,
280+ ] ) ;
281+ console . info ( "Signature:" , signature ) ;
282+
283+ txData . signatures = signature ;
284+
285+ const result = await safeContract . execTransaction (
286+ txData . to ,
287+ txData . value ,
288+ txData . data ,
289+ txData . operation ,
290+ txData . safeTxGas ,
291+ txData . baseGas ,
292+ txData . gasPrice ,
293+ txData . gasToken ,
294+ txData . refundReceiver ,
295+ txData . signatures
296+ ) ;
297+
298+ return Boolean ( result ) ;
299+ }
0 commit comments