Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 15 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,17 @@ jobs:
with:
node-version: "20.14.0"

- name: Get Yarn cache directory path
id: yarn-cache-dir-path
run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT

- name: Retrieve yarn cache
uses: actions/cache@v4
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }}
restore-keys: ${{ runner.os }}-yarn-

- name: Setup CI Environment
run: make setup

Expand All @@ -44,19 +55,16 @@ jobs:
- name: Run move tests
run: make test

- name: Run move prover
run: |
export BOOGIE_EXE=/home/runner/.local/bin/boogie
export CVC5_EXE=/home/runner/.local/bin/cvc5
export Z3_EXE=/home/runner/.local/bin/z3
make prove

- name: Start network
run: make start-network

- name: Run Typescript tests
run: yarn test

- name: Stop network
if: ${{ always() }}
run: make stop-network

scan:
if: github.event_name == 'pull_request'
uses: circlefin/circle-public-github-workflows/.github/workflows/pr-scan.yaml@v1
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
# === Move compiler settings ===

# Refer to https://github.com/aptos-labs/aptos-core/blob/687937182b30f32895d13e4384a96e03f569468c/third_party/move/move-model/src/metadata.rs#L80
compiler_version = 1
compiler_version = 2

# Refer to https://github.com/aptos-labs/aptos-core/blob/687937182b30f32895d13e4384a96e03f569468c/third_party/move/move-model/src/metadata.rs#L179
# NOTE: The bytecode_version used during compilation is auto-inferred from this setting. Refer to https://github.com/aptos-labs/aptos-core/blob/687937182b30f32895d13e4384a96e03f569468c/third_party/move/move-model/src/metadata.rs#L235-L241
# for more information.
language_version = 1
language_version = 2

setup:
@bash scripts/shell/setup.sh
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"license": "Apache-2.0",
"homepage": "https://github.com/circlefin/stablecoin-aptos#readme",
"devDependencies": {
"@aptos-labs/ts-sdk": "1.29.1",
"@aptos-labs/ts-sdk": "1.33.0",
"@types/mocha": "10.0.6",
"@types/sinon": "17.0.3",
"@typescript-eslint/eslint-plugin": "7.11.0",
Expand All @@ -38,5 +38,6 @@
"engines": {
"node": "20.14.0",
"yarn": "1.x.x"
}
},
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
}
2 changes: 1 addition & 1 deletion packages/aptos_extensions/Move.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ deployer = "0xaa03675e2e13043f3d591804b0d8a8ffb775d14b11ca0831866ecdf48df26713"

[dependencies.AptosFramework]
git = "https://github.com/aptos-labs/aptos-core.git"
rev = "mainnet"
rev = "1381c93fd5a656f16fb326d4ffe371947554a330"
subdir = "aptos-move/framework/aptos-framework"

[dev-dependencies]
2 changes: 1 addition & 1 deletion packages/stablecoin/Move.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ upgrade_policy = "compatible"

[dependencies.AptosFramework]
git = "https://github.com/aptos-labs/aptos-core.git"
rev = "mainnet"
rev = "1381c93fd5a656f16fb326d4ffe371947554a330"
subdir = "aptos-move/framework/aptos-framework"

[dependencies.AptosExtensions]
Expand Down
60 changes: 38 additions & 22 deletions scripts/shell/setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,34 +16,50 @@
# See the License for the specific language governing permissions and
# limitations under the License.

set -e

if [[ "$CI" == true ]]
then
OS="Ubuntu-22.04-x86_64"
else
OS="macOS-arm64"
fi

echo ">> Setting up environment"


# ==== Aptos installation ====
APTOS_CLI_VERSION="4.2.6"
APTOS_CLI_VERSION="7.5.0"
APTOS_BIN="${APTOS_BIN:-$HOME/.aptos/bin}"

if [ "$CI" == true ]; then
curl -sSfL -o /tmp/aptos.zip "https://github.com/aptos-labs/aptos-core/releases/download/aptos-cli-v$APTOS_CLI_VERSION/aptos-cli-$APTOS_CLI_VERSION-Ubuntu-22.04-x86_64.zip"
sudo unzip /tmp/aptos.zip -d /usr/local/bin
sudo chmod +x /usr/local/bin/*
else
if [ "$(brew ls --versions aptos)" != "aptos $APTOS_CLI_VERSION" ]; then
brew uninstall --force aptos && \
# aptos 4.2.6's formula
curl -s -o aptos.rb https://raw.githubusercontent.com/Homebrew/homebrew-core/ef458cb0a2574eb7d451090cbedc3942b77a7284/Formula/a/aptos.rb
brew install --formula aptos.rb
brew pin aptos
rm aptos.rb
if ! command -v aptos &> /dev/null || ! aptos -V | grep -q "aptos $APTOS_CLI_VERSION"
then
echo "Installing Aptos binary from Github..."
echo ">> Version: '$APTOS_CLI_VERSION'"
echo ">> OS: '$OS'"

# Download and extract Aptos binaries.
rm -rf "$APTOS_BIN"
mkdir -p "$APTOS_BIN"
curl -L -o "$APTOS_BIN/aptos-v$APTOS_CLI_VERSION.zip" "https://github.com/aptos-labs/aptos-core/releases/download/aptos-cli-v$APTOS_CLI_VERSION/aptos-cli-$APTOS_CLI_VERSION-$OS.zip"
unzip -o "$APTOS_BIN/aptos-v$APTOS_CLI_VERSION.zip" -d "$APTOS_BIN"
rm "$APTOS_BIN/aptos-v$APTOS_CLI_VERSION.zip"

# Sanity check that the Aptos binary was installed correctly
echo "Checking aptos installation..."
if ! "$APTOS_BIN/aptos" -V | grep -q "aptos $APTOS_CLI_VERSION"
then
echo "Aptos binary was not installed correctly"
exit 1
fi
fi

# ==== Movefmt & Move prover installation ====
if [ -z $APTOS_BIN ]
then
aptos update movefmt
aptos update prover-dependencies
else
aptos update movefmt --install-dir $APTOS_BIN
aptos update prover-dependencies --install-dir $APTOS_BIN
if [[ "$CI" == true ]]
then
echo "$APTOS_BIN" >> $GITHUB_PATH
else
echo " Aptos binary installed successfully. Run the following command to add 'aptos' to your shell"
echo " echo 'export PATH=\"$APTOS_BIN:\$PATH\"' >> ~/.zshrc"
fi
fi


Expand Down
170 changes: 170 additions & 0 deletions scripts/typescript/decodeTransaction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
/**
* Copyright 2024 Circle Internet Group, Inc. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import {
AccountAddress,
Deserializable,
Deserializer,
EntryFunctionArgument,
EntryFunctionBytes,
FixedBytes,
Hex,
MoveVector,
Serializable,
SimpleTransaction,
TransactionPayloadEntryFunction,
U8
} from "@aptos-labs/ts-sdk";
import { program } from "commander";
import fs from "fs";
import path from "path";
import { REPOSITORY_ROOT } from "./utils";

export default program
.createCommand("decode-transaction")
.description("Decodes transaction bytes into a human-readable format.")
.requiredOption(
"--tx-bytes <string>",
"Hex-encoded, BCS-serialized transaction"
)
.requiredOption("-o, --output <string>", "The output file path.")
.option(
"--function-name <string>",
"The name of the function that is being decoded. Required for argument decoding."
)
.action(async (options) => {
await decodeTransaction(options);
});

export async function decodeTransaction({
txBytes,
output,
functionName
}: {
txBytes: string;
output: string;
functionName?: string;
}) {
// Deserialize the transaction bytes into a SimpleTransaction.
const tx = SimpleTransaction.deserialize(
new Deserializer(Hex.fromHexString(txBytes).toUint8Array())
);

if (!(tx.rawTransaction.payload instanceof TransactionPayloadEntryFunction)) {
throw new Error(
"Only transactions with entry function payloads are supported."
);
}

const txPayload = tx.rawTransaction.payload.entryFunction;

// Attempt to decode the arguments for the function.
const txPayloadArguments = txPayload.args as EntryFunctionBytes[];
const isArgDecoderSupportedForFunction =
functionName != null &&
Object.keys(argumentDecoders).includes(functionName);

if (!isArgDecoderSupportedForFunction) {
console.log(
`NOTE: Argument decoding is either disabled or is unsupported for the entry function called. The decoded transaction will return the arguments as its raw BCS-serialized bytes.`
);
}

const args = isArgDecoderSupportedForFunction
? txPayloadArguments.map((arg, i) =>
argumentDecoders[functionName][i](arg.value)
)
: txPayloadArguments.map((arg) => arg.bcsToHex().toString());

// Decode the transaction.
const decodedTx = {
sender: tx.rawTransaction.sender.toString(),
sequenceNumber: tx.rawTransaction.sequence_number.toString(),
maxGasAmount: tx.rawTransaction.max_gas_amount.toString(),
gasUnitPrice: tx.rawTransaction.gas_unit_price.toString(),
expirationTimestampSecs:
tx.rawTransaction.expiration_timestamp_secs.toString(),
chainId: tx.rawTransaction.chain_id.chainId.toString(),
feePayer: tx.feePayerAddress?.toString(),
payload: {
function: `${txPayload.module_name.address.toString()}::${txPayload.module_name.name.identifier}::${txPayload.function_name.identifier}`,
typeArgs: txPayload.type_args.map((tyArg) => tyArg.toString()),
args
}
};

// Write the decoded transaction to a file.
const outputFilePath = path.join(REPOSITORY_ROOT, output);
console.log(
`\u001b[32mTransaction successfully decoded and saved to: '${outputFilePath}'\u001b[0m`
);
fs.writeFileSync(outputFilePath, JSON.stringify(decodedTx, null, 2));
}

// ==== Argument Decoders ====
const argumentDecoders: Record<string, ((arg: FixedBytes) => any)[]> = {
// aptos_extensions::upgradable::upgrade_package
upgradePackage: [
// resource_acct: address,
(arg: FixedBytes) =>
AccountAddress.deserialize(new Deserializer(arg.value)).toString(),

// metadata_serialized: vector<u8>,
(arg: FixedBytes) => {
const vector = MoveVector.deserialize(new Deserializer(arg.value), U8);
return convertMoveVectorU8ToHex(vector);
},

// code: vector<vector<u8>>
(arg: FixedBytes) => {
const vector = TwoLevelMoveVector.deserialize(
new Deserializer(arg.value),
U8
);
return vector.values.map(convertMoveVectorU8ToHex);
}
]
};

/**
* Referenced from {@link https://github.com/aptos-labs/aptos-ts-sdk/blob/34539a96eb51c2605f759ec3615624a8489988e9/src/bcs/serializable/moveStructs.ts#L289-L319}
*/
class TwoLevelMoveVector {
static deserialize<T extends Serializable & EntryFunctionArgument>(
deserializer: Deserializer,
cls: Deserializable<T>
): MoveVector<MoveVector<T>> {
const length = deserializer.deserializeUleb128AsU32();
const values: Array<MoveVector<T>> = [];
for (let i = 0; i < length; i += 1) {
values.push(MoveVector.deserialize(deserializer, cls));
}
return new MoveVector(values);
}
}

/**
* Converts a MoveVector<U8> into a hex string.
*
* @param moveVector - The MoveVector<U8> to convert.
* @returns The hex string representation of the MoveVector<U8>.
*/
function convertMoveVectorU8ToHex(moveVector: MoveVector<U8>) {
const byteArray = Uint8Array.from(moveVector.values.map((u8) => u8.value));
return `0x${Buffer.from(byteArray).toString("hex")}`;
}
Loading
Loading