Skip to content

Commit

Permalink
Refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
h0ngcha0 committed Apr 18, 2024
1 parent 7d0dfa9 commit 2742982
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 29 deletions.
10 changes: 0 additions & 10 deletions packages/cli/src/codegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,15 +96,6 @@ function formatParameters(fieldsSig: { names: string[]; types: string[] }): stri
}

function genCallMethod(contractName: string, functionSig: node.FunctionSig): string {
// if (functionSig.returnTypes.length === 0) {
// const retType = `${contractName}Types.SignExecuteMethodResult<'${functionSig.name}'>`
// const params = `params: ${contractName}Types.SignExecuteMethodParams<'${functionSig.name}'>`
// return `
// ${functionSig.name}: async (${params}): Promise<${retType}> => {
// return signExecuteMethod(${contractName}, this, "${functionSig.name}", params)
// }
// `
// } else {
const retType = `${contractName}Types.CallMethodResult<'${functionSig.name}'>`
const funcHasArgs = functionSig.paramNames.length > 0
const params = `params${funcHasArgs ? '' : '?'}: ${contractName}Types.CallMethodParams<'${functionSig.name}'>`
Expand All @@ -114,7 +105,6 @@ function genCallMethod(contractName: string, functionSig: node.FunctionSig): str
return callMethod(${contractName}, this, "${functionSig.name}", ${callParams}, getContractByCodeHash)
}
`
// }
}

function genCallMethods(contract: Contract): string {
Expand Down
46 changes: 32 additions & 14 deletions packages/web3/src/contract/contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,18 @@ import {
Assert,
StoreMutFieldByIndex,
DestroySelf,
byteStringCodec
Pop,
byteStringCodec,
StoreLocal,
instrCodec,
U256Const,
Instr,
ApproveToken,
ApproveAlph,
CallExternal,
Dup,
CallerAddress,
ByteConst
} from '../codec'

const crypto = new WebCrypto()
Expand Down Expand Up @@ -2286,7 +2297,7 @@ export async function signExecuteMethod<I extends ContractInstance, F extends Fi
const methodIndex = contract.contract.getMethodIndex(methodName)
const functionSig = contract.contract.functions[methodIndex]

const bytecodeTemplate = encodeBytecodeTemplate(methodIndex, functionSig, contract.contract.structs, params.approve)
const bytecodeTemplate = getBytecodeTemplate(methodIndex, functionSig, contract.contract.structs, params.approve)

const fieldsSig = toFieldsSig(contract.contract.name, functionSig)
const bytecode = ralph.buildScriptByteCode(
Expand All @@ -2311,7 +2322,7 @@ export async function signExecuteMethod<I extends ContractInstance, F extends Fi
return await signer.signAndSubmitExecuteScriptTx(signerParams)
}

function encodeBytecodeTemplate(
function getBytecodeTemplate(
methodIndex: number,
functionSig: FunctionSig,
structs: Struct[],
Expand All @@ -2320,9 +2331,10 @@ function encodeBytecodeTemplate(
tokens?: Token[]
}
): string {
// For the default TxScript main function
const numberOfMethods = '01'
const isPublic = '01'
const modifier = '03'
const modifier = functionSig.usePreapprovedAssets ? '03' : '00'
const argsLength = '00'
const returnsLength = '00'

Expand All @@ -2332,7 +2344,7 @@ function encodeBytecodeTemplate(
const approveTokensInstrs: string[] = getApproveTokensInstrs(approve?.tokens)
const callerInstrs: string[] = getCallAddressInstrs(approveAlphInstrs.length / 2 + approveTokensInstrs.length / 3)

// -1 because the first template var is the contract
// First template var is the contract
const functionArgsNum = encodeU256Const(BigInt(templateVarsLength - 1))
const localsLength = (templateVarStoreLocalInstrs.length / 2).toString(16).padStart(2, '0')

Expand All @@ -2342,11 +2354,11 @@ function encodeBytecodeTemplate(
(acc, returnType) => acc + ralph.typeLength(returnType, structs),
0
)
const functionReturnPopInstrs = '18'.repeat(functionReturnTypesLength)
const functionReturnPopInstrs = encodeInstr(Pop).repeat(functionReturnTypesLength)
const functionReturnNum = encodeU256Const(BigInt(functionReturnTypesLength))

const contractTemplateVar = '{0}' // always the 1st argument
const externalCallInstr = '01' + methodIndex.toString(16).padStart(2, '0')
const externalCallInstr = encodeInstr(CallExternal(methodIndex))
const numberOfInstrs = compactSignedIntCodec
.encodeI32(
callerInstrs.length +
Expand Down Expand Up @@ -2385,7 +2397,7 @@ function getApproveAlphInstrs(attoAlphAmount?: Number256): string[] {
if (attoAlphAmount) {
const approvedAttoAlphAmount = encodeU256Const(BigInt(attoAlphAmount))
approveAlphInstrs.push(approvedAttoAlphAmount)
approveAlphInstrs.push('a2') // ApproveAlph
approveAlphInstrs.push(encodeInstr(ApproveAlph))
}

return approveAlphInstrs
Expand All @@ -2399,7 +2411,7 @@ function getApproveTokensInstrs(tokens?: Token[]): string[] {
const tokenAmount = encodeU256Const(BigInt(token.amount))
approveTokensInstrs.push('1440' + tokenId.toString('hex'))
approveTokensInstrs.push(tokenAmount)
approveTokensInstrs.push('a3') // ApproveToken
approveTokensInstrs.push(encodeInstr(ApproveToken))
})
}

Expand All @@ -2409,10 +2421,11 @@ function getApproveTokensInstrs(tokens?: Token[]): string[] {
function getCallAddressInstrs(approveAssetsNum: number): string[] {
const callerInstrs: string[] = []
if (approveAssetsNum > 0) {
callerInstrs.push('b4') // callerAddress
callerInstrs.push(encodeInstr(CallerAddress))

const dup = encodeInstr(Dup)
if (approveAssetsNum > 1) {
callerInstrs.push(...new Array(approveAssetsNum - 1).fill('7a')) // dup
callerInstrs.push(...new Array(approveAssetsNum - 1).fill(dup))
}
}

Expand Down Expand Up @@ -2471,14 +2484,15 @@ function encodeStoreLocalInstr(index: number): string {
if (index < 0 || index > 0xff) {
throw new Error(`StoreLocal index ${index} must be between 0 and 255 inclusive`)
}
return '17' + index.toString(16).padStart(2, '0')
return encodeInstr(StoreLocal(index))
}

function encodeLoadLocalInstr(index: number): string {
if (index < 0 || index > 0xff) {
throw new Error(`LoadLocal index ${index} must be between 0 and 255 inclusive`)
}
return '16' + index.toString(16).padStart(2, '0')

return encodeInstr(LoadLocal(index))
}

function encodeU256Const(value: bigint): string {
Expand All @@ -2489,10 +2503,14 @@ function encodeU256Const(value: bigint): string {
if (value < 6) {
return (BigInt(0x0c) + value).toString(16).padStart(2, '0')
} else {
return '13' + compactUnsignedIntCodec.encodeU256(BigInt(value)).toString('hex')
return encodeInstr(U256Const(compactUnsignedIntCodec.fromU256(BigInt(value))))
}
}

function encodeInstr(instr: Instr): string {
return instrCodec.encode(instr).toString('hex')
}

function toFieldsSig(contractName: string, functionSig: FunctionSig): FieldsSig {
return {
names: ['__contract__'].concat(functionSig.paramNames),
Expand Down
25 changes: 20 additions & 5 deletions test/contract.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -545,10 +545,13 @@ describe('contract', function () {
.contractInstance
const provider = web3.getCurrentNodeProvider()

const state = await provider.contracts.getContractsAddressState(add.address)
expect(state).toBeDefined()
const stateBefore = await provider.contracts.getContractsAddressState(add.address)
expect(stateBefore.mutFields[0].value).toEqual('0')

await add.transaction.add({ args: { array: [2n, 1n] }, signer })

const stateAfter = await provider.contracts.getContractsAddressState(add.address)
expect(stateAfter.mutFields[0].value).toEqual('3')
})

it('should test sign execute method with struct arguments', async () => {
Expand All @@ -557,8 +560,8 @@ describe('contract', function () {
.contractInstance
const provider = web3.getCurrentNodeProvider()

const state = await provider.contracts.getContractsAddressState(add.address)
expect(state).toBeDefined()
const stateBefore = await provider.contracts.getContractsAddressState(add.address)
expect(stateBefore.mutFields[0].value).toEqual('0')

await add.transaction.add2({
args: {
Expand All @@ -575,6 +578,9 @@ describe('contract', function () {
},
signer
})

const stateAfter = await provider.contracts.getContractsAddressState(add.address)
expect(stateAfter.mutFields[0].value).toEqual('3')
})

it('should test sign execute method with approved assets', async () => {
Expand All @@ -590,7 +596,11 @@ describe('contract', function () {

const state = await provider.contracts.getContractsAddressState(add.address)
expect(state).toBeDefined()
await add.transaction.createSubContractAndTransfer({

const beforeBalances = await signer.nodeProvider.addresses.getAddressesAddressBalance(signerAddress)
expect(beforeBalances.tokenBalances?.find((t) => t.id === sub.contractInstance.contractId)!.amount).toEqual('300')

const txResult = await add.transaction.createSubContractAndTransfer({
args: {
a: 1n,
path: stringToHex('test-path'),
Expand All @@ -605,5 +615,10 @@ describe('contract', function () {
tokens: [{ id: sub.contractInstance.contractId, amount: 200n }]
}
})

const afterBalances = await signer.nodeProvider.addresses.getAddressesAddressBalance(signerAddress)
const gasFee = BigInt(txResult.gasAmount) * BigInt(txResult.gasPrice)
expect(BigInt(beforeBalances.balance)).toEqual(BigInt(afterBalances.balance) + ONE_ALPH / 10n + gasFee)
expect(afterBalances.tokenBalances?.find((t) => t.id === sub.contractInstance.contractId)!.amount).toEqual('100')
})
})

0 comments on commit 2742982

Please sign in to comment.