0

There is currently a published contract on the main chain (contract A for short), I must use another contract .somefunction (contract B for short) to call A.somefunction(), but A.somefunction() already uses msg.sender to bring in to use. The following are examples

Contract Acoin is ERC20{
    struct Staking {
    uint256 Coin;
    uint256 ArriveCoin;
    uint256 ArriveTime;
    uint256 Time;
    uint256 State; 
    }
    mapping(address => Staking[]) public All_Staking;
    constructor(string memory name, string memory symbol) ERC20(name,symbol){}
    function SearchStaking() public view returns (Staking[] memory) {
        require(All_Staking[msg.sender].length > 0,"Sorry, This account does not have any Token staking");
        return All_Staking[msg.sender];
    }
}

So I need to write B contract to use msg.sender(caller not B contract) to call SearchStaking of A contract and get the array of AContract.Staking[], if I use All_Staking to call, I can get a single result but no array length.

import "./ACoin.sol";

Contract B is ERC20{ Acoin public ACoin; Acoin.Staking[] private Staking; constructor(string memory name, string memory symbol,address _A) ERC20(name,symbol){ ACoin = Acoin(_A); } function GetUserAllStaking() public view returns(Acoin.Staking[] memory){ return ACoin.SearchStaking(); ---->Here should using msg.sender not Contract B address } }

iop04329
  • 11
  • 1

1 Answers1

0

Use delegatecall.

(bool success, bytes memory data) = ACoin.delegatecall(
        abi.encodeWithSignature("SearchStaking()")
);

Note: for this to work you need that bought contract A and B will have the same storage layout.

matank001
  • 820
  • 4
  • 16
  • I recommend reading the below link for a better understanding: https://solidity-by-example.org/delegatecall/ – Payam Safaei Oct 18 '22 at 08:11
  • Yes,i tried,and the code tell me to fix like this (bool success, bytes memory data) = address(_A).delegatecall(abi.encodeWithSignature("SearchStaking()")); – iop04329 Oct 18 '22 at 08:22
  • But there is a problem the Contract A SearchStaking() returns(Staking[] memory) And i call the B contract GetUserAllStaking to return abi.decode(data, (uint256,uint256,uint256,uint256,uint256)); There is a tuple like(uint,uint,uint,uint,uint) But the contract A SearchStaking() return a tuple(uint,uint,uint,uint,uint)[] Example: tuple(uint256,uint256,uint256,uint256,uint256)[]: 1000,1020,1668660432,1666068432,0,1000,1020,1671252456,1666068456,0 – iop04329 Oct 18 '22 at 08:30
  • You need to parse and fix the return values. Because you use low level call – matank001 Oct 18 '22 at 11:32
  • 1
    The answer is not correct. DelegateCall doesn't "call" another contract, it executes the other contract's bytecode within the actual contract. The call won't be able to update the target contract storage. It is mostly used for proxy contracts. It shouldn't be used for unrelated contracts. – Ismael Oct 19 '22 at 20:28
  • @Ismael but like, in his situation this would work I guess – matank001 Oct 20 '22 at 03:53
  • @matank001 Unfortunately it wont work in this case. Contract A is already deployed, and he wants to write contract B to execute a function from A with the original msg.sender. If B delegatecalls a function from A, it will be running A bytecode but it will be writing B's storage. The call might revert if contracts do not have the same storage layout, or worse it will make unintended changes. – Ismael Oct 21 '22 at 01:06
  • Yes I see, they do have different memory layouts, I’ll edit – matank001 Oct 21 '22 at 07:04