@@ -682,12 +682,17 @@ async function ensureAliceHasFaucetAsset(
682682 console . log ( `Alice faucet asset (${ faucetAsset } ) balance after mint: ${ afterBal } ` )
683683}
684684
685- export function deriveEthAddress ( ) : {
685+ export function deriveEthAddress (
686+ path : string ,
687+ palletSS58 : string ,
688+ ) : {
686689 derivedPubKey : string
687690 derivedEthAddress : string
688691} {
689692 const derivedPubKey = KeyDerivation . derivePublicKey (
690693 ENV . ROOT_PUBLIC_KEY ,
694+ palletSS58 ,
695+ path ,
691696 ENV . SUBSTRATE_CHAIN_ID ,
692697 )
693698
@@ -716,11 +721,12 @@ export async function ensureDerivedEthHasGas(
716721
717722 if ( ethBalance >= estimatedGas ) return
718723
719- if ( ENV . EVM_NETWORK === 'anvil' ) {
720- const ANVIL_DEFAULT_KEY = '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80'
721- const funder = new ethers . Wallet ( ANVIL_DEFAULT_KEY , provider )
724+ const ANVIL_DEFAULT_KEY = '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80'
725+ const funderKey = ENV . EVM_NETWORK === 'anvil' ? ANVIL_DEFAULT_KEY : ENV . EVM_FUNDER_KEY
726+ if ( funderKey ) {
727+ const funder = new ethers . Wallet ( funderKey , provider )
722728 const fundAmount = estimatedGas * 10n
723- console . log ( `Funding ${ derivedEthAddress } with ${ ethers . formatEther ( fundAmount ) } ETH from Anvil account ...` )
729+ console . log ( `Funding ${ derivedEthAddress } with ${ ethers . formatEther ( fundAmount ) } ETH...` )
724730 const tx = await funder . sendTransaction ( { to : derivedEthAddress , value : fundAmount } )
725731 await tx . wait ( )
726732 console . log ( `Funded. Tx: ${ tx . hash } ` )
@@ -731,7 +737,7 @@ export async function ensureDerivedEthHasGas(
731737 `Insufficient ETH at ${ derivedEthAddress } \n` +
732738 ` Need: ${ ethers . formatEther ( estimatedGas ) } ETH\n` +
733739 ` Have: ${ ethers . formatEther ( ethBalance ) } ETH\n` +
734- ` Please fund this address with ETH for gas` ,
740+ ` Fund this address with ETH for gas, or set EVM_FUNDER_KEY to auto-fund ` ,
735741 )
736742}
737743
@@ -759,7 +765,15 @@ export async function ensureFaucetMpcAddress(
759765
760766 console . log ( `Setting faucet MPC to derived address ${ derivedEthAddress } ...` )
761767 // Use Anvil account 0 (deployer/owner) to call setMPC
762- const ownerKey = '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80'
768+ const ANVIL_OWNER_KEY = '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80'
769+ const ownerKey = ENV . EVM_NETWORK === 'anvil' ? ANVIL_OWNER_KEY : ENV . FAUCET_OWNER_KEY
770+ if ( ! ownerKey ) {
771+ throw new Error (
772+ `Faucet MPC is ${ currentMpc } but derived address is ${ derivedEthAddress } .\n` +
773+ ` Set FAUCET_OWNER_KEY (owner of ${ ENV . FAUCET_ADDRESS } ) to auto-setMPC, ` +
774+ `or call setMPC(${ derivedEthAddress } ) manually from the owner.` ,
775+ )
776+ }
763777 const ownerWallet = new ethers . Wallet ( ownerKey , provider )
764778 const contractWithSigner = faucetContract . connect ( ownerWallet )
765779 const tx = await ( contractWithSigner as any ) . setMPC ( derivedEthAddress )
@@ -860,14 +874,15 @@ export async function executeAsRoot(
860874 return
861875 }
862876
863- // Try TC path first — much faster than governance referendum
864877 const isTcMember = await isSignerTcMember ( api , signer )
865878 if ( isTcMember ) {
866- await executeViaTechCommittee ( api , signer , call , label )
867- return
879+ const applied = await executeViaTechCommittee ( api , signer , call , label )
880+ if ( applied ) return
881+ console . log ( `${ label } : TC motion did not apply the call (needs Root); falling back to referendum` )
882+ } else {
883+ console . log ( `${ label } : signer is not a TC member, using referendum` )
868884 }
869885
870- console . log ( `${ label } : signer is not a TC member, falling back to referendum` )
871886 await executeAsRootViaReferendum ( api , signer , call , label )
872887}
873888
@@ -953,7 +968,7 @@ async function executeViaTechCommittee(
953968 signer : any ,
954969 call : SubmittableExtrinsic < 'promise' > ,
955970 label : string ,
956- ) {
971+ ) : Promise < boolean > {
957972 const members = await ( api . query as any ) . technicalCommittee . members ( )
958973 const memberList = members . toJSON ( ) as string [ ]
959974 const memberCount = memberList . length
@@ -981,20 +996,26 @@ async function executeViaTechCommittee(
981996 }
982997 }
983998
984- // Check if the call was executed (Executed event = threshold was 1 or auto-closed)
985- const executed = result . events . some (
986- ( r : any ) =>
987- r . event . section === 'technicalCommittee' &&
988- ( r . event . method === 'Executed' || r . event . method === 'Closed' ) ,
989- )
999+ for ( const { event } of result . events ) {
1000+ if ( event . section === 'technicalCommittee' && event . method === 'Executed' ) {
1001+ const res : any = ( event . data as any ) . result ?? event . data [ 1 ]
1002+ if ( res && res . isErr ) {
1003+ console . warn ( `${ label } : TC motion executed but inner call failed: ${ res . asErr . toString ( ) } ` )
1004+ return false
1005+ }
1006+ console . log ( `${ label } : TC proposal executed immediately` )
1007+ return true
1008+ }
1009+ }
9901010
991- if ( executed ) {
992- console . log ( `${ label } : TC proposal executed immediately` )
993- } else if ( threshold > 1 ) {
1011+ if ( threshold > 1 ) {
9941012 console . log ( `${ label } : TC proposal needs ${ threshold - 1 } more Aye votes from other members` )
9951013 // Poll for execution (other TC members may vote via separate process)
9961014 await pollForTcExecution ( api , result , label )
1015+ return true
9971016 }
1017+
1018+ return false
9981019}
9991020
10001021/**
0 commit comments