`run_external` fails with TS SDK

Using the run_external callframe fails with the following error:

Proxy:

// SPDX-License-Identifier: Apache-2.0
contract;
 
use std::{
	call_frames::first_param,
	context::*,
	asset::*,
	execution::run_external,
	hash::Hash,
    hash::sha256,
};
 
abi Proxy {
    #[storage(read, write)]
    fn set_proxy_target(new_target: ContractId);
}

// Inspired by EIP-2535: Diamonds, Multifacet proxy
#[namespace(diamonds)]
storage {
    SRC14 {
        /// The [ContractId] of the target contract.
        ///
        /// # Additional Information
        ///
        /// `target` is stored at sha256("storage_SRC14_0")
        target in 0x7bb458adc1d118713319a5baa00a2d049dd64d2916477d2688d76970c898cd55: ContractId = ContractId::zero(),
    },
}

impl Proxy for Contract {
    #[storage(read, write)]
    fn set_proxy_target(new_target: ContractId) {
        storage::SRC14.target.write(new_target);
    }
}

#[fallback]
#[storage(read)]
fn fallback() {
    run_external(storage::SRC14.target.read())
}

ProxyImplementation

// SPDX-License-Identifier: Apache-2.0
contract;
 
use std::{context::*, asset::*};
 
abi ProxyImpl {
    #[storage(read,write)]
    fn set_bits(value: b256);

    #[storage(read)]
    fn get_bits() -> b256;
}

storage {
	implementation1 {
    	bits: b256 = 0x0000000000000000000000000000000000000000000000000000000000000000,
	},
}

impl ProxyImpl for Contract {
    #[storage(read,write)]
    fn set_bits(value: b256) {
        storage::implementation1.bits.write(value);
    }

    #[storage(read)]
    fn get_bits() -> b256 {
        storage::implementation1.bits.read()
    }
}

Test:

const proxy = await deploy("Proxy", deployer)
const proxyImpl = await deploy("ProxyImpl", deployer)

const bits = (await diamondProxyImpl.functions.get_bits().get()).value
console.log("bits", bits) // 0x0000000000000000000000000000000000000000000000000000000000000000

// setting target
let target = (await diamondProxy.functions.proxy_target().get()).value
console.log("proxy target before", target)
;(await diamondProxy.functions.set_proxy_target(toContract(diamondProxyImpl)).call()).waitForResult()
target = (await diamondProxy.functions.proxy_target().get()).value
console.log("proxy target after", target)

const newProxy = new ProxyImpl(diamondProxy.id, deployer)
// fails here
const newBits = (await newProxy.functions.get_bits().get()).value
console.log("new bits", newBits)

I will look into the issue. in the meanwhile, can you share the output for fuelup show and the SDK version you are using?

fuelup show:

latest-aarch64-apple-darwin
  forc : 0.63.5
    - forc-client
      - forc-deploy : 0.63.5
      - forc-run : 0.63.5
    - forc-crypto : 0.63.5
    - forc-debug : 0.63.5
    - forc-doc : 0.63.5
    - forc-fmt : 0.63.5
    - forc-lsp : 0.63.5
    - forc-tx : 0.63.5
    - forc-wallet : 0.9.0
  fuel-core : 0.35.0
  fuel-core-keygen : 0.35.0

fuels versions
--------------
forc : 0.66.4
forc-wallet : 0.66.0

TS SDK version: v0.94.5

Can you please upgrade your versions to below: fuel-core: 0.36.0, forc: 0.64.0 and ts SDK: 0.94.8? also, can you please ensure all the contracts are correctly compiled, and deployed and addresses are correct?

@theAusicist what is happening inside the deploy function? My hunch is that the storage slots haven’t been initialised correctly?

Also semi-related, I would recommend working with this SRC14 implementation as the ownership is far more secure.

Also, our own fuels deploy command uses the proxy deploy under the hood, so you can check out it’s usage here. A proxy deploy and call that uses run_external can be found here.

2 Likes