mirror of
https://github.com/alexgo-io/stacks-subnets.git
synced 2026-01-12 22:43:44 +08:00
feat: remove deposit function name
Use "deposit-from-burnchain" always, because it will be validated by a trait.
This commit is contained in:
@@ -4,6 +4,7 @@ import {
|
||||
AnchorMode,
|
||||
standardPrincipalCV,
|
||||
uintCV,
|
||||
someCV,
|
||||
PostConditionMode,
|
||||
contractPrincipalCV,
|
||||
broadcastTransaction,
|
||||
@@ -38,10 +39,12 @@ async function main() {
|
||||
contractName: "subnet-alpha",
|
||||
functionName: "withdraw-nft-asset",
|
||||
functionArgs: [
|
||||
contractPrincipalCV(contractAddr, 'simple-nft-l1'), // nft-contract
|
||||
uintCV(5), // ID
|
||||
standardPrincipalCV(addr), // recipient
|
||||
contractPrincipalCV(contractAddr, 'simple-nft-l1'), // nft-contract
|
||||
contractPrincipalCV(contractAddr, 'simple-nft-l1'), // nft-mint-contract
|
||||
uintCV(withdrawalId), // withdrawal ID
|
||||
uintCV(withdrawalBlockHeight), // withdrawal block height
|
||||
someCV(contractPrincipalCV(contractAddr, 'simple-nft-l1')), // nft-mint-contract
|
||||
cv_merkle_entry.withdrawal_root, // withdrawal root
|
||||
cv_merkle_entry.withdrawal_leaf_hash, // withdrawal leaf hash
|
||||
cv_merkle_entry.sibling_hashes ], // sibling hashes
|
||||
|
||||
@@ -2,6 +2,7 @@ import {
|
||||
makeContractCall,
|
||||
AnchorMode,
|
||||
standardPrincipalCV,
|
||||
contractPrincipalCV,
|
||||
uintCV,
|
||||
broadcastTransaction,
|
||||
PostConditionMode
|
||||
@@ -17,10 +18,11 @@ async function main() {
|
||||
const nonce = parseInt(process.argv[2]);
|
||||
|
||||
const txOptions = {
|
||||
contractAddress: contractAddr,
|
||||
contractName: 'simple-nft-l2',
|
||||
functionName: 'withdraw-nft-asset',
|
||||
contractAddress: 'ST000000000000000000002AMW42H',
|
||||
contractName: 'subnet',
|
||||
functionName: 'nft-withdraw?',
|
||||
functionArgs: [
|
||||
contractPrincipalCV(contractAddr, 'simple-nft-l2'),
|
||||
uintCV(5), // ID
|
||||
standardPrincipalCV(addr), // recipient
|
||||
],
|
||||
|
||||
@@ -1,48 +1,66 @@
|
||||
|
||||
[project]
|
||||
name = "core-contracts"
|
||||
name = 'core-contracts'
|
||||
description = ''
|
||||
authors = []
|
||||
telemetry = false
|
||||
cache_dir = '.cache'
|
||||
|
||||
[contracts.trait-standards]
|
||||
path = "contracts/helper/trait-standards.clar"
|
||||
clarity_version = 2
|
||||
epoch = 2.1
|
||||
[[project.requirements]]
|
||||
contract_id = 'SP2PABAF9FTAJYNFZH93XENAJ8FVY99RRM50D2JG9.nft-trait'
|
||||
|
||||
[contracts.simple-nft]
|
||||
path = "contracts/helper/simple-nft.clar"
|
||||
clarity_version = 2
|
||||
epoch = 2.1
|
||||
[[project.requirements]]
|
||||
contract_id = 'SP3FBR2AGK5H9QBDH3EEN6DF8EK8JY7RX8QJ5SVTE.sip-010-trait-ft-standard'
|
||||
|
||||
[contracts.simple-nft-no-mint]
|
||||
path = "contracts/helper/simple-nft-no-mint.clar"
|
||||
clarity_version = 2
|
||||
epoch = 2.1
|
||||
|
||||
[contracts.second-simple-nft]
|
||||
path = "contracts/helper/simple-nft.clar"
|
||||
clarity_version = 2
|
||||
epoch = 2.1
|
||||
|
||||
[contracts.simple-ft]
|
||||
path = "contracts/helper/simple-ft.clar"
|
||||
[contracts.multi-miner]
|
||||
path = 'contracts/multi-miner.clar'
|
||||
clarity_version = 2
|
||||
epoch = 2.1
|
||||
|
||||
[contracts.second-simple-ft]
|
||||
path = "contracts/helper/simple-ft.clar"
|
||||
path = 'contracts/helper/simple-ft.clar'
|
||||
clarity_version = 2
|
||||
epoch = 2.1
|
||||
|
||||
[contracts.second-simple-nft]
|
||||
path = 'contracts/helper/simple-nft.clar'
|
||||
clarity_version = 2
|
||||
epoch = 2.1
|
||||
|
||||
[contracts.simple-ft]
|
||||
path = 'contracts/helper/simple-ft.clar'
|
||||
clarity_version = 2
|
||||
epoch = 2.1
|
||||
|
||||
[contracts.simple-nft]
|
||||
path = 'contracts/helper/simple-nft.clar'
|
||||
clarity_version = 2
|
||||
epoch = 2.1
|
||||
|
||||
[contracts.simple-nft-no-mint]
|
||||
path = 'contracts/helper/simple-nft-no-mint.clar'
|
||||
clarity_version = 2
|
||||
epoch = 2.1
|
||||
|
||||
[contracts.subnet]
|
||||
path = "contracts/subnet.clar"
|
||||
clarity_version = 2
|
||||
epoch = 2.1
|
||||
|
||||
[contracts.multi-miner]
|
||||
path = "contracts/multi-miner.clar"
|
||||
path = 'contracts/subnet.clar'
|
||||
clarity_version = 2
|
||||
epoch = 2.1
|
||||
|
||||
[contracts.test-helpers]
|
||||
path = "contracts/helper/test-helpers.clar"
|
||||
path = 'contracts/helper/test-helpers.clar'
|
||||
clarity_version = 2
|
||||
epoch = 2.1
|
||||
|
||||
[contracts.subnet-traits]
|
||||
path = 'contracts/helper/subnet-traits.clar'
|
||||
clarity_version = 2
|
||||
epoch = 2.1
|
||||
|
||||
[repl.analysis]
|
||||
passes = []
|
||||
|
||||
[repl.analysis.check_checker]
|
||||
strict = false
|
||||
trusted_sender = false
|
||||
trusted_caller = false
|
||||
callee_filter = false
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
(define-trait ft-trait
|
||||
(
|
||||
;; Transfer from the caller to a new principal
|
||||
(transfer (uint principal principal (optional (buff 34))) (response bool uint))
|
||||
|
||||
;; the human readable name of the token
|
||||
(get-name () (response (string-ascii 32) uint))
|
||||
|
||||
;; the ticker symbol, or empty if none
|
||||
(get-symbol () (response (string-ascii 32) uint))
|
||||
|
||||
;; the number of decimals used, e.g. 6 would mean 1_000_000 represents 1 token
|
||||
(get-decimals () (response uint uint))
|
||||
|
||||
;; the balance of the passed principal
|
||||
(get-balance (principal) (response uint uint))
|
||||
|
||||
;; the current total supply (which does not need to be a constant)
|
||||
(get-total-supply () (response uint uint))
|
||||
|
||||
;; an optional URI that represents metadata of this token
|
||||
(get-token-uri () (response (optional (string-utf8 256)) uint))
|
||||
)
|
||||
)
|
||||
@@ -1,6 +0,0 @@
|
||||
(define-trait mint-from-subnet-trait
|
||||
(
|
||||
;; Transfer from the sender to a new principal
|
||||
(mint-from-subnet (uint principal principal) (response bool uint))
|
||||
)
|
||||
)
|
||||
@@ -1,15 +0,0 @@
|
||||
(define-trait nft-trait
|
||||
(
|
||||
;; Last token ID, limited to uint range
|
||||
(get-last-token-id () (response uint uint))
|
||||
|
||||
;; URI for metadata associated with the token
|
||||
(get-token-uri (uint) (response (optional (string-ascii 256)) uint))
|
||||
|
||||
;; Owner of a given token identifier
|
||||
(get-owner (uint) (response (optional principal) uint))
|
||||
|
||||
;; Transfer from the sender to a new principal
|
||||
(transfer (uint principal principal) (response bool uint))
|
||||
)
|
||||
)
|
||||
@@ -1,7 +1,7 @@
|
||||
(define-constant ERR_NOT_AUTHORIZED (err u1001))
|
||||
|
||||
(impl-trait .trait-standards.ft-trait)
|
||||
(impl-trait .trait-standards.mint-from-subnet-trait)
|
||||
(impl-trait 'SP3FBR2AGK5H9QBDH3EEN6DF8EK8JY7RX8QJ5SVTE.sip-010-trait-ft-standard.sip-010-trait)
|
||||
(impl-trait .subnet-traits.mint-from-subnet-trait)
|
||||
|
||||
(define-fungible-token ft-token)
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
(define-constant ERR_NOT_AUTHORIZED (err u1001))
|
||||
|
||||
(impl-trait .trait-standards.nft-trait)
|
||||
(impl-trait 'ST000000000000000000002AMW42H.subnet.nft-trait)
|
||||
|
||||
(define-data-var lastId uint u0)
|
||||
|
||||
@@ -45,16 +45,20 @@
|
||||
)
|
||||
)
|
||||
|
||||
;; deposit function
|
||||
(define-public (subnet-deposit-nft-token (id uint) (recipient principal))
|
||||
(begin
|
||||
(nft-mint? nft-token id recipient)
|
||||
)
|
||||
(impl-trait 'ST000000000000000000002AMW42H.subnet.subnet-asset)
|
||||
|
||||
;; Called for deposit from the burnchain to the subnet
|
||||
(define-public (deposit-from-burnchain (id uint) (recipient principal))
|
||||
(begin
|
||||
(asserts! (is-eq tx-sender 'ST000000000000000000002AMW42H.subnet) ERR_NOT_AUTHORIZED)
|
||||
(nft-mint? nft-token id recipient)
|
||||
)
|
||||
)
|
||||
|
||||
;; withdraw function
|
||||
(define-public (withdraw-nft-asset (id uint) (recipient principal))
|
||||
(begin
|
||||
(nft-withdraw? nft-token id recipient)
|
||||
)
|
||||
;; Called for withdrawal from the subnet to the burnchain
|
||||
(define-public (burn-for-withdrawal (id uint) (owner principal))
|
||||
(begin
|
||||
(asserts! (is-eq tx-sender owner) ERR_NOT_AUTHORIZED)
|
||||
(nft-burn? nft-token id owner)
|
||||
)
|
||||
)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
(define-constant ERR_NOT_AUTHORIZED (err u1001))
|
||||
|
||||
(impl-trait .trait-standards.nft-trait)
|
||||
(impl-trait 'SP2PABAF9FTAJYNFZH93XENAJ8FVY99RRM50D2JG9.nft-trait.nft-trait)
|
||||
|
||||
(define-data-var lastId uint u0)
|
||||
(define-map CFG_BASE_URI bool (string-ascii 256))
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
|
||||
(define-constant ERR_NOT_AUTHORIZED (err u1001))
|
||||
|
||||
(impl-trait .trait-standards.nft-trait)
|
||||
(impl-trait .trait-standards.mint-from-subnet-trait)
|
||||
(impl-trait 'SP2PABAF9FTAJYNFZH93XENAJ8FVY99RRM50D2JG9.nft-trait.nft-trait)
|
||||
(impl-trait .subnet-traits.mint-from-subnet-trait)
|
||||
|
||||
(define-data-var lastId uint u0)
|
||||
(define-map CFG_BASE_URI bool (string-ascii 256))
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
(define-trait nft-trait
|
||||
(
|
||||
;; Last token ID, limited to uint range
|
||||
(get-last-token-id () (response uint uint))
|
||||
|
||||
;; URI for metadata associated with the token
|
||||
(get-token-uri (uint) (response (optional (string-ascii 256)) uint))
|
||||
|
||||
;; Owner of a given token identifier
|
||||
(get-owner (uint) (response (optional principal) uint))
|
||||
|
||||
;; Transfer from the sender to a new principal
|
||||
(transfer (uint principal principal) (response bool uint))
|
||||
)
|
||||
)
|
||||
|
||||
(define-trait mint-from-subnet-trait
|
||||
(
|
||||
;; Transfer from the sender to a new principal
|
||||
(mint-from-subnet (uint principal principal) (response bool uint))
|
||||
)
|
||||
)
|
||||
|
||||
(define-trait ft-trait
|
||||
(
|
||||
;; Transfer from the caller to a new principal
|
||||
(transfer (uint principal principal (optional (buff 34))) (response bool uint))
|
||||
|
||||
;; the human readable name of the token
|
||||
(get-name () (response (string-ascii 32) uint))
|
||||
|
||||
;; the ticker symbol, or empty if none
|
||||
(get-symbol () (response (string-ascii 32) uint))
|
||||
|
||||
;; the number of decimals used, e.g. 6 would mean 1_000_000 represents 1 token
|
||||
(get-decimals () (response uint uint))
|
||||
|
||||
;; the balance of the passed principal
|
||||
(get-balance (principal) (response uint uint))
|
||||
|
||||
;; the current total supply (which does not need to be a constant)
|
||||
(get-total-supply () (response uint uint))
|
||||
|
||||
;; an optional URI that represents metadata of this token
|
||||
(get-token-uri () (response (optional (string-utf8 256)) uint))
|
||||
)
|
||||
)
|
||||
@@ -38,9 +38,9 @@
|
||||
(define-map allowed-contracts principal principal)
|
||||
|
||||
;; Use trait declarations
|
||||
(use-trait nft-trait .trait-standards.nft-trait)
|
||||
(use-trait ft-trait .trait-standards.ft-trait)
|
||||
(use-trait mint-from-subnet-trait .trait-standards.mint-from-subnet-trait)
|
||||
(use-trait nft-trait 'SP2PABAF9FTAJYNFZH93XENAJ8FVY99RRM50D2JG9.nft-trait.nft-trait)
|
||||
(use-trait ft-trait 'SP3FBR2AGK5H9QBDH3EEN6DF8EK8JY7RX8QJ5SVTE.sip-010-trait-ft-standard.sip-010-trait)
|
||||
(use-trait mint-from-subnet-trait .subnet-traits.mint-from-subnet-trait)
|
||||
|
||||
;; Update the miner for this contract.
|
||||
(define-public (update-miner (new-miner principal))
|
||||
@@ -293,7 +293,8 @@
|
||||
(withdrawal-id uint)
|
||||
(height uint)
|
||||
(nft-mint-contract (optional <mint-from-subnet-trait>))
|
||||
(withdrawal-root (buff 32)) (withdrawal-leaf-hash (buff 32))
|
||||
(withdrawal-root (buff 32))
|
||||
(withdrawal-leaf-hash (buff 32))
|
||||
(sibling-hashes (list 50 {
|
||||
hash: (buff 32),
|
||||
is-left-side: bool,
|
||||
|
||||
@@ -293,12 +293,7 @@ impl StacksSubnetOp {
|
||||
})
|
||||
}
|
||||
"\"deposit-ft\"" => {
|
||||
// Parse 5 fields: ft-amount, ft-name, l1-contract-id, subnet-contract-id, and sender
|
||||
let amount = tuple
|
||||
.get("ft-amount")
|
||||
.map_err(|_| "No 'ft-amount' field in Clarity tuple")?
|
||||
.clone()
|
||||
.expect_u128();
|
||||
// Parse 5 fields: l1-contract-id, ft-name, ft-amount, sender, and subnet-contract-id
|
||||
let l1_contract_id = tuple
|
||||
.get("l1-contract-id")
|
||||
.map_err(|_| "No 'l1-contract-id' field in Clarity tuple")?
|
||||
@@ -309,6 +304,21 @@ impl StacksSubnetOp {
|
||||
} else {
|
||||
Err("Expected 'l1-contract-id' to be a contract principal")
|
||||
}?;
|
||||
let name = tuple
|
||||
.get("ft-name")
|
||||
.map_err(|_| "No 'ft-name' field in Clarity tuple")?
|
||||
.clone()
|
||||
.expect_ascii();
|
||||
let amount = tuple
|
||||
.get("ft-amount")
|
||||
.map_err(|_| "No 'ft-amount' field in Clarity tuple")?
|
||||
.clone()
|
||||
.expect_u128();
|
||||
let sender = tuple
|
||||
.get("sender")
|
||||
.map_err(|_| "No 'sender' field in Clarity tuple")?
|
||||
.clone()
|
||||
.expect_principal();
|
||||
let subnet_contract_id = tuple
|
||||
.get("subnet-contract-id")
|
||||
.map_err(|_| "No 'subnet-contract-id' field in Clarity tuple")?
|
||||
@@ -319,23 +329,6 @@ impl StacksSubnetOp {
|
||||
} else {
|
||||
Err("Expected 'subnet-contract-id' to be a contract principal")
|
||||
}?;
|
||||
let name = tuple
|
||||
.get("ft-name")
|
||||
.map_err(|_| "No 'ft-name' field in Clarity tuple")?
|
||||
.clone()
|
||||
.expect_ascii();
|
||||
let sender = tuple
|
||||
.get("sender")
|
||||
.map_err(|_| "No 'sender' field in Clarity tuple")?
|
||||
.clone()
|
||||
.expect_principal();
|
||||
let subnet_function_name = tuple
|
||||
.get("subnet-function-name")
|
||||
.map_err(|_| "No 'subnet-function-name' field in Clarity tuple")?
|
||||
.clone()
|
||||
.expect_ascii();
|
||||
let subnet_function_name = ClarityName::try_from(subnet_function_name)
|
||||
.map_err(|e| format!("Failed to parse Clarity name: {:?}", e))?;
|
||||
|
||||
Ok(Self {
|
||||
txid,
|
||||
@@ -345,7 +338,6 @@ impl StacksSubnetOp {
|
||||
event: StacksSubnetOpType::DepositFt {
|
||||
l1_contract_id,
|
||||
subnet_contract_id,
|
||||
subnet_function_name,
|
||||
name,
|
||||
amount,
|
||||
sender,
|
||||
@@ -353,12 +345,7 @@ impl StacksSubnetOp {
|
||||
})
|
||||
}
|
||||
"\"deposit-nft\"" => {
|
||||
// Parse 4 fields: nft-id, l1-contract-id, subnet-contract-id, and sender
|
||||
let id = tuple
|
||||
.get("nft-id")
|
||||
.map_err(|_| "No 'nft-id' field in Clarity tuple")?
|
||||
.clone()
|
||||
.expect_u128();
|
||||
// Parse 4 fields: l1-contract-id, nft-id, sender, and subnet-contract-id
|
||||
// check that this is a valid way of getting the ID of the L1 contract.
|
||||
let l1_contract_id = tuple
|
||||
.get("l1-contract-id")
|
||||
@@ -370,6 +357,16 @@ impl StacksSubnetOp {
|
||||
} else {
|
||||
Err("Expected 'l1-contract-id' to be a contract principal")
|
||||
}?;
|
||||
let id = tuple
|
||||
.get("nft-id")
|
||||
.map_err(|_| "No 'nft-id' field in Clarity tuple")?
|
||||
.clone()
|
||||
.expect_u128();
|
||||
let sender = tuple
|
||||
.get("sender")
|
||||
.map_err(|_| "No 'sender' field in Clarity tuple")?
|
||||
.clone()
|
||||
.expect_principal();
|
||||
let subnet_contract_id = tuple
|
||||
.get("subnet-contract-id")
|
||||
.map_err(|_| "No 'subnet-contract-id' field in Clarity tuple")?
|
||||
@@ -380,18 +377,6 @@ impl StacksSubnetOp {
|
||||
} else {
|
||||
Err("Expected 'subnet-contract-id' to be a contract principal")
|
||||
}?;
|
||||
let sender = tuple
|
||||
.get("sender")
|
||||
.map_err(|_| "No 'sender' field in Clarity tuple")?
|
||||
.clone()
|
||||
.expect_principal();
|
||||
let subnet_function_name = tuple
|
||||
.get("subnet-function-name")
|
||||
.map_err(|_| "No 'subnet-function-name' field in Clarity tuple")?
|
||||
.clone()
|
||||
.expect_ascii();
|
||||
let subnet_function_name = ClarityName::try_from(subnet_function_name)
|
||||
.map_err(|e| format!("Failed to parse Clarity name: {:?}", e))?;
|
||||
|
||||
Ok(Self {
|
||||
txid,
|
||||
@@ -401,7 +386,6 @@ impl StacksSubnetOp {
|
||||
event: StacksSubnetOpType::DepositNft {
|
||||
l1_contract_id,
|
||||
subnet_contract_id,
|
||||
subnet_function_name,
|
||||
id,
|
||||
sender,
|
||||
},
|
||||
|
||||
@@ -208,7 +208,6 @@ pub enum StacksSubnetOpType {
|
||||
DepositFt {
|
||||
l1_contract_id: QualifiedContractIdentifier,
|
||||
subnet_contract_id: QualifiedContractIdentifier,
|
||||
subnet_function_name: ClarityName,
|
||||
name: String,
|
||||
amount: u128,
|
||||
sender: PrincipalData,
|
||||
@@ -216,7 +215,6 @@ pub enum StacksSubnetOpType {
|
||||
DepositNft {
|
||||
l1_contract_id: QualifiedContractIdentifier,
|
||||
subnet_contract_id: QualifiedContractIdentifier,
|
||||
subnet_function_name: ClarityName,
|
||||
id: u128,
|
||||
sender: PrincipalData,
|
||||
},
|
||||
|
||||
@@ -302,7 +302,6 @@ impl FromRow<DepositFtOp> for DepositFtOp {
|
||||
let l1_contract_id = QualifiedContractIdentifier::from_column(row, "l1_contract_id")?;
|
||||
let subnet_contract_id =
|
||||
QualifiedContractIdentifier::from_column(row, "subnet_contract_id")?;
|
||||
let subnet_function_name = ClarityName::from_column(row, "subnet_function_name")?;
|
||||
let name: String = row.get_unwrap("name");
|
||||
let amount_str: String = row.get_unwrap("amount");
|
||||
let amount =
|
||||
@@ -314,7 +313,6 @@ impl FromRow<DepositFtOp> for DepositFtOp {
|
||||
burn_header_hash,
|
||||
l1_contract_id,
|
||||
subnet_contract_id,
|
||||
subnet_function_name,
|
||||
name,
|
||||
amount,
|
||||
sender: PrincipalData::from(sender),
|
||||
@@ -330,7 +328,6 @@ impl FromRow<DepositNftOp> for DepositNftOp {
|
||||
let l1_contract_id = QualifiedContractIdentifier::from_column(row, "l1_contract_id")?;
|
||||
let subnet_contract_id =
|
||||
QualifiedContractIdentifier::from_column(row, "subnet_contract_id")?;
|
||||
let subnet_function_name = ClarityName::from_column(row, "subnet_function_name")?;
|
||||
let id_str: String = row.get_unwrap("id");
|
||||
let id = u128::from_str_radix(&id_str, 10).expect("CORRUPTION: bad u128 written to sortdb");
|
||||
let sender = StacksAddress::from_column(row, "sender")?;
|
||||
@@ -340,7 +337,6 @@ impl FromRow<DepositNftOp> for DepositNftOp {
|
||||
burn_header_hash,
|
||||
l1_contract_id,
|
||||
subnet_contract_id,
|
||||
subnet_function_name,
|
||||
id,
|
||||
sender: PrincipalData::from(sender),
|
||||
})
|
||||
@@ -439,7 +435,6 @@ const SORTITION_DB_INITIAL_SCHEMA: &'static [&'static str] = &[
|
||||
l1_block_id TEXT NOT NULL,
|
||||
l1_contract_id TEXT NOT NULL,
|
||||
subnet_contract_id TEXT NOT NULL,
|
||||
subnet_function_name TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
amount TEXT NOT NULL,
|
||||
sender TEXT NOT NULL,
|
||||
@@ -454,7 +449,6 @@ const SORTITION_DB_INITIAL_SCHEMA: &'static [&'static str] = &[
|
||||
l1_block_id TEXT NOT NULL,
|
||||
l1_contract_id TEXT NOT NULL,
|
||||
subnet_contract_id TEXT NOT NULL,
|
||||
subnet_function_name TEXT NOT NULL,
|
||||
id TEXT NOT NULL,
|
||||
sender TEXT NOT NULL,
|
||||
sortition_id TEXT NOT NULL,
|
||||
@@ -3085,7 +3079,6 @@ impl<'a> SortitionHandleTx<'a> {
|
||||
"txid" => %op.txid,
|
||||
"l1_contract_id" => %op.l1_contract_id,
|
||||
"subnet_contract_id" => %op.subnet_contract_id,
|
||||
"subnet_function_name" => %op.subnet_function_name,
|
||||
"name" => %op.name,
|
||||
"amount" => %op.amount,
|
||||
"sender" => %op.sender,
|
||||
@@ -3101,7 +3094,6 @@ impl<'a> SortitionHandleTx<'a> {
|
||||
"txid" => %op.txid,
|
||||
"l1_contract_id" => %op.l1_contract_id,
|
||||
"subnet_contract_id" => %op.subnet_contract_id,
|
||||
"subnet_function_name" => %op.subnet_function_name,
|
||||
"id" => %op.id,
|
||||
"sender" => %op.sender,
|
||||
);
|
||||
@@ -3208,14 +3200,13 @@ impl<'a> SortitionHandleTx<'a> {
|
||||
&op.burn_header_hash,
|
||||
&op.l1_contract_id.to_string(),
|
||||
&op.subnet_contract_id.to_string(),
|
||||
&op.subnet_function_name.to_string(),
|
||||
&op.name,
|
||||
&op.amount.to_string(),
|
||||
&op.sender.to_string(),
|
||||
sort_id,
|
||||
];
|
||||
|
||||
self.execute("REPLACE INTO deposit_ft (txid, l1_block_id, l1_contract_id, subnet_contract_id, subnet_function_name, name, amount, sender, sortition_id) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9)", args)?;
|
||||
self.execute("REPLACE INTO deposit_ft (txid, l1_block_id, l1_contract_id, subnet_contract_id, name, amount, sender, sortition_id) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8)", args)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -3231,13 +3222,12 @@ impl<'a> SortitionHandleTx<'a> {
|
||||
&op.burn_header_hash,
|
||||
&op.l1_contract_id.to_string(),
|
||||
&op.subnet_contract_id.to_string(),
|
||||
&op.subnet_function_name.to_string(),
|
||||
&op.id.to_string(),
|
||||
&op.sender.to_string(),
|
||||
sort_id,
|
||||
];
|
||||
|
||||
self.execute("REPLACE INTO deposit_nft (txid, l1_block_id, l1_contract_id, subnet_contract_id, subnet_function_name, id, sender, sortition_id) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8)", args)?;
|
||||
self.execute("REPLACE INTO deposit_nft (txid, l1_block_id, l1_contract_id, subnet_contract_id, id, sender, sortition_id) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)", args)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ impl TryFrom<&StacksSubnetOp> for DepositFtOp {
|
||||
if let StacksSubnetOpType::DepositFt {
|
||||
ref l1_contract_id,
|
||||
ref subnet_contract_id,
|
||||
ref subnet_function_name,
|
||||
ref name,
|
||||
ref amount,
|
||||
ref sender,
|
||||
@@ -24,7 +23,6 @@ impl TryFrom<&StacksSubnetOp> for DepositFtOp {
|
||||
burn_header_hash: BurnchainHeaderHash(value.in_block.0.clone()),
|
||||
l1_contract_id: l1_contract_id.clone(),
|
||||
subnet_contract_id: subnet_contract_id.clone(),
|
||||
subnet_function_name: subnet_function_name.clone(),
|
||||
name: name.clone(),
|
||||
amount: amount.clone(),
|
||||
sender: sender.clone(),
|
||||
|
||||
@@ -12,7 +12,6 @@ impl TryFrom<&StacksSubnetOp> for DepositNftOp {
|
||||
if let StacksSubnetOpType::DepositNft {
|
||||
ref l1_contract_id,
|
||||
ref subnet_contract_id,
|
||||
ref subnet_function_name,
|
||||
ref id,
|
||||
ref sender,
|
||||
} = value.event
|
||||
@@ -23,7 +22,6 @@ impl TryFrom<&StacksSubnetOp> for DepositNftOp {
|
||||
burn_header_hash: BurnchainHeaderHash(value.in_block.0.clone()),
|
||||
l1_contract_id: l1_contract_id.clone(),
|
||||
subnet_contract_id: subnet_contract_id.clone(),
|
||||
subnet_function_name: subnet_function_name.clone(),
|
||||
id: id.clone(),
|
||||
sender: sender.clone(),
|
||||
})
|
||||
|
||||
@@ -247,8 +247,6 @@ pub struct DepositFtOp {
|
||||
pub l1_contract_id: QualifiedContractIdentifier,
|
||||
// Contract ID on subnet for this fungible token
|
||||
pub subnet_contract_id: QualifiedContractIdentifier,
|
||||
// Name of the function to call in the subnet contract to execute deposit
|
||||
pub subnet_function_name: ClarityName,
|
||||
// Name of fungible token
|
||||
pub name: String,
|
||||
// Amount of the fungible token that was deposited
|
||||
@@ -268,8 +266,6 @@ pub struct DepositNftOp {
|
||||
pub l1_contract_id: QualifiedContractIdentifier,
|
||||
// Contract ID on subnet for this NFT
|
||||
pub subnet_contract_id: QualifiedContractIdentifier,
|
||||
// Name of the function to call in the subnet contract to execute deposit
|
||||
pub subnet_function_name: ClarityName,
|
||||
// The ID of the NFT transferred
|
||||
pub id: u128,
|
||||
// The principal that performed the deposit
|
||||
|
||||
@@ -42,14 +42,29 @@
|
||||
)
|
||||
)
|
||||
|
||||
(define-trait mint-from-subnet-trait
|
||||
(define-trait subnet-asset
|
||||
(
|
||||
;; Transfer from the sender to a new principal
|
||||
(mint-from-subnet (uint principal principal) (response bool uint))
|
||||
;; Process a deposit from the burnchain.
|
||||
(deposit-from-burnchain
|
||||
(
|
||||
uint ;; asset-id (NFT) or amount (FT)
|
||||
principal ;; recipient
|
||||
)
|
||||
(response bool uint)
|
||||
)
|
||||
|
||||
;; Burn the asset for withdrawal from the subnet.
|
||||
(burn-for-withdrawal
|
||||
(
|
||||
uint ;; asset-id (NFT) or amount (FT)
|
||||
principal ;; owner
|
||||
)
|
||||
(response bool uint)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
(define-public (ft-withdraw? (asset <ft-trait>) (amount uint) (sender principal))
|
||||
(define-public (ft-withdraw? (asset <subnet-asset>) (amount uint) (sender principal))
|
||||
(begin
|
||||
(print {
|
||||
type: "ft",
|
||||
@@ -57,11 +72,11 @@
|
||||
amount: amount,
|
||||
asset-contract: (contract-of asset),
|
||||
})
|
||||
(contract-call? asset transfer amount sender (as-contract tx-sender) none)
|
||||
(contract-call? asset burn-for-withdrawal amount sender)
|
||||
)
|
||||
)
|
||||
|
||||
(define-public (nft-withdraw? (asset <nft-trait>) (id uint) (sender principal))
|
||||
(define-public (nft-withdraw? (asset <subnet-asset>) (id uint) (sender principal))
|
||||
(begin
|
||||
(print {
|
||||
type: "nft",
|
||||
@@ -69,7 +84,7 @@
|
||||
id: id,
|
||||
asset-contract: (contract-of asset),
|
||||
})
|
||||
(contract-call? asset transfer id sender (as-contract tx-sender))
|
||||
(contract-call? asset burn-for-withdrawal id sender)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -91,6 +91,8 @@ use clarity::vm::ClarityVersion;
|
||||
use rusqlite::types::ToSqlOutput;
|
||||
use stacks_common::types::chainstate::{StacksAddress, StacksBlockId};
|
||||
|
||||
static DEPOSIT_FUNCTION_NAME: &str = "deposit-from-burnchain";
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct StagingMicroblock {
|
||||
pub consensus_hash: ConsensusHash,
|
||||
@@ -4722,7 +4724,6 @@ impl StacksChainState {
|
||||
txid,
|
||||
burn_header_hash,
|
||||
subnet_contract_id,
|
||||
subnet_function_name,
|
||||
amount,
|
||||
sender,
|
||||
..
|
||||
@@ -4733,7 +4734,7 @@ impl StacksChainState {
|
||||
&sender.clone(),
|
||||
None,
|
||||
&subnet_contract_id,
|
||||
&*subnet_function_name,
|
||||
DEPOSIT_FUNCTION_NAME,
|
||||
&[Value::UInt(amount), Value::Principal(sender)],
|
||||
|_, _| false,
|
||||
)
|
||||
@@ -4782,7 +4783,6 @@ impl StacksChainState {
|
||||
txid,
|
||||
burn_header_hash,
|
||||
subnet_contract_id,
|
||||
subnet_function_name,
|
||||
id,
|
||||
sender,
|
||||
..
|
||||
@@ -4792,7 +4792,7 @@ impl StacksChainState {
|
||||
&sender.clone(),
|
||||
None,
|
||||
&subnet_contract_id,
|
||||
&*subnet_function_name,
|
||||
DEPOSIT_FUNCTION_NAME,
|
||||
&[Value::UInt(id), Value::Principal(sender)],
|
||||
|_, _| false,
|
||||
)
|
||||
@@ -11410,25 +11410,10 @@ pub mod test {
|
||||
StandardPrincipalData::from(addr_publisher),
|
||||
ContractName::from("subnet-deposit-contract"),
|
||||
),
|
||||
subnet_function_name: ClarityName::from("subnet-deposit-ft-token"),
|
||||
name: "ft-token".to_string(),
|
||||
amount: 2,
|
||||
sender: PrincipalData::from(addr_publisher),
|
||||
},
|
||||
// this op calls a function that does not exist in the designated subnet contract
|
||||
DepositFtOp {
|
||||
txid: Txid([2; 32]),
|
||||
burn_header_hash: BurnchainHeaderHash([0; 32]),
|
||||
l1_contract_id: QualifiedContractIdentifier::local("l1-contract").unwrap(),
|
||||
subnet_contract_id: QualifiedContractIdentifier::new(
|
||||
StandardPrincipalData::from(addr_publisher),
|
||||
ContractName::from("subnet-deposit-contract"),
|
||||
),
|
||||
subnet_function_name: ClarityName::from("subnet-deposit-ft-token-DNE"),
|
||||
name: "ft-token".to_string(),
|
||||
amount: 5,
|
||||
sender: PrincipalData::from(addr_publisher),
|
||||
},
|
||||
// this op tries to call a function in an unregistered contract
|
||||
DepositFtOp {
|
||||
txid: Txid([1; 32]),
|
||||
@@ -11438,7 +11423,6 @@ pub mod test {
|
||||
StandardPrincipalData::from(addr_publisher),
|
||||
ContractName::from("subnet-deposit-contract-DNE"),
|
||||
),
|
||||
subnet_function_name: ClarityName::from("subnet-deposit-ft-token"),
|
||||
name: "ft-token".to_string(),
|
||||
amount: 2,
|
||||
sender: PrincipalData::from(addr_publisher),
|
||||
@@ -11474,8 +11458,20 @@ pub mod test {
|
||||
let subnet_simple_nft = "
|
||||
(define-non-fungible-token nft-token uint)
|
||||
|
||||
(define-public (subnet-deposit-nft-token (id uint) (recipient principal))
|
||||
(nft-mint? nft-token id recipient)
|
||||
(impl-trait 'ST000000000000000000002AMW42H.subnet.subnet-asset)
|
||||
|
||||
(define-public (deposit-from-burnchain (id uint) (recipient principal))
|
||||
(begin
|
||||
(asserts! (is-eq tx-sender 'ST000000000000000000002AMW42H.subnet) ERR_NOT_AUTHORIZED)
|
||||
(nft-mint? nft-token id recipient)
|
||||
)
|
||||
)
|
||||
|
||||
(define-public (burn-for-withdrawal (id uint) (owner principal))
|
||||
(begin
|
||||
(asserts! (is-eq tx-sender owner) ERR_NOT_AUTHORIZED)
|
||||
(nft-burn? nft-token id owner)
|
||||
)
|
||||
)
|
||||
|
||||
(define-read-only (get-token-owner (id uint))
|
||||
@@ -11517,33 +11513,6 @@ pub mod test {
|
||||
StandardPrincipalData::from(addr_publisher),
|
||||
ContractName::from("subnet-deposit-contract"),
|
||||
),
|
||||
subnet_function_name: ClarityName::from("subnet-deposit-nft-token"),
|
||||
id: 2,
|
||||
sender: PrincipalData::from(addr_publisher),
|
||||
},
|
||||
// this op calls a function that does not exist in the designated subnet contract
|
||||
DepositNftOp {
|
||||
txid: Txid([1; 32]),
|
||||
burn_header_hash: BurnchainHeaderHash([0; 32]),
|
||||
l1_contract_id: QualifiedContractIdentifier::local("l1-contract").unwrap(),
|
||||
subnet_contract_id: QualifiedContractIdentifier::new(
|
||||
StandardPrincipalData::from(addr_publisher),
|
||||
ContractName::from("subnet-deposit-contract"),
|
||||
),
|
||||
subnet_function_name: ClarityName::from("subnet-deposit-nft-token-DNE"),
|
||||
id: 2,
|
||||
sender: PrincipalData::from(addr_publisher),
|
||||
},
|
||||
// this op tries to call a function in an unregistered contract
|
||||
DepositNftOp {
|
||||
txid: Txid([1; 32]),
|
||||
burn_header_hash: BurnchainHeaderHash([0; 32]),
|
||||
l1_contract_id: QualifiedContractIdentifier::local("l1-contract").unwrap(),
|
||||
subnet_contract_id: QualifiedContractIdentifier::new(
|
||||
StandardPrincipalData::from(addr_publisher),
|
||||
ContractName::from("subnet-deposit-contract-DNE"),
|
||||
),
|
||||
subnet_function_name: ClarityName::from("subnet-deposit-nft-token"),
|
||||
id: 2,
|
||||
sender: PrincipalData::from(addr_publisher),
|
||||
},
|
||||
|
||||
@@ -261,11 +261,11 @@ pub fn publish_subnet_contracts_to_l1(
|
||||
config: &Config,
|
||||
miner: PrincipalData,
|
||||
) -> u64 {
|
||||
let trait_standard_contract_name = "trait-standards";
|
||||
let trait_standard_contract_name = "subnet-traits";
|
||||
let l1_rpc_origin = config.burnchain.get_rpc_url();
|
||||
// Publish the trait contract
|
||||
let trait_content =
|
||||
include_str!("../../../../core-contracts/contracts/helper/trait-standards.clar");
|
||||
include_str!("../../../../core-contracts/contracts/helper/subnet-traits.clar");
|
||||
let trait_publish = make_contract_publish(
|
||||
&MOCKNET_PRIVATE_KEY_1,
|
||||
LAYER_1_CHAIN_ID_TESTNET,
|
||||
@@ -433,7 +433,7 @@ fn l1_deposit_and_withdraw_asset_integration_test() {
|
||||
// Start Stacks L1.
|
||||
let l1_toml_file = "../../contrib/conf/stacks-l1-mocknet.toml";
|
||||
let l1_rpc_origin = "http://127.0.0.1:20443";
|
||||
let trait_standard_contract_name = "trait-standards";
|
||||
let trait_standard_contract_name = "subnet-traits";
|
||||
|
||||
// Start the L2 run loop.
|
||||
let mut config = super::new_l1_test_conf(&*MOCKNET_PRIVATE_KEY_2, &*MOCKNET_PRIVATE_KEY_1);
|
||||
@@ -475,7 +475,7 @@ fn l1_deposit_and_withdraw_asset_integration_test() {
|
||||
|
||||
// Publish the NFT/FT/Subnet traits
|
||||
let trait_content =
|
||||
include_str!("../../../../core-contracts/contracts/helper/trait-standards.clar");
|
||||
include_str!("../../../../core-contracts/contracts/helper/subnet-traits.clar");
|
||||
let trait_publish = make_contract_publish(
|
||||
&MOCKNET_PRIVATE_KEY_1,
|
||||
LAYER_1_CHAIN_ID_TESTNET,
|
||||
@@ -1331,7 +1331,7 @@ fn l1_deposit_and_withdraw_stx_integration_test() {
|
||||
// Start Stacks L1.
|
||||
let l1_toml_file = "../../contrib/conf/stacks-l1-mocknet.toml";
|
||||
let l1_rpc_origin = "http://127.0.0.1:20443";
|
||||
let trait_standard_contract_name = "trait-standards";
|
||||
let trait_standard_contract_name = "subnet-traits";
|
||||
|
||||
// Start the L2 run loop.
|
||||
let mut config = super::new_l1_test_conf(&*MOCKNET_PRIVATE_KEY_2, &*MOCKNET_PRIVATE_KEY_1);
|
||||
@@ -1378,7 +1378,7 @@ fn l1_deposit_and_withdraw_stx_integration_test() {
|
||||
|
||||
// Publish the NFT/FT/Subnet traits
|
||||
let trait_content =
|
||||
include_str!("../../../../core-contracts/contracts/helper/trait-standards.clar");
|
||||
include_str!("../../../../core-contracts/contracts/helper/subnet-traits.clar");
|
||||
let trait_publish = make_contract_publish(
|
||||
&MOCKNET_PRIVATE_KEY_1,
|
||||
LAYER_1_CHAIN_ID_TESTNET,
|
||||
@@ -1881,7 +1881,7 @@ fn nft_deposit_and_withdraw_integration_test() {
|
||||
// Start Stacks L1.
|
||||
let l1_toml_file = "../../contrib/conf/stacks-l1-mocknet.toml";
|
||||
let l1_rpc_origin = "http://127.0.0.1:20443";
|
||||
let trait_standards_contract_name = "trait-standards";
|
||||
let trait_standards_contract_name = "subnet-traits";
|
||||
|
||||
// Start the L2 run loop.
|
||||
let mut config = super::new_test_conf();
|
||||
@@ -1937,7 +1937,7 @@ fn nft_deposit_and_withdraw_integration_test() {
|
||||
|
||||
// Publish the NFT/FT/mint-from-subnet traits onto L1
|
||||
let trait_content =
|
||||
include_str!("../../../../core-contracts/contracts/helper/trait-standards.clar");
|
||||
include_str!("../../../../core-contracts/contracts/helper/subnet-traits.clar");
|
||||
let trait_publish = make_contract_publish(
|
||||
&MOCKNET_PRIVATE_KEY_1,
|
||||
LAYER_1_CHAIN_ID_TESTNET,
|
||||
@@ -2029,7 +2029,7 @@ fn nft_deposit_and_withdraw_integration_test() {
|
||||
|
||||
// Publish subnet contract for nft-token
|
||||
let subnet_simple_nft = "
|
||||
(impl-trait .trait-standards.nft-trait)
|
||||
(impl-trait .subnet-traits.nft-trait)
|
||||
|
||||
(define-constant ERR_NOT_AUTHORIZED (err u1001))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user