(초보)Klaytn IDE에서 제가 만든 토큰을 특정 토큰 Contract 주소로 오송금을 하였습니다 해결방법이 있을까요?

우선 답변드리는 개발자님들에게 고생하신다는 말부터 올리겠습니다.

  1. a는 저고 b는 타인을 지칭합니다.
    a가 토큰을 b에게 보냈는데 b가 저에게 보낸다는걸 토큰 contract 주소 추가를 실수로 코인 contract에게 오송금을 하였습니다. 이를 해결할 방법이 있을까요?

  2. IDE에서 Transfer from과 burn from 후 mint 를 통해 소각 후 재 발행을 시도했으나 단순 burn, mint 기능은 잘 되는데 어쩐지 저 from 명령문만 gas estimate fail 이라는 오류가 발생합니다. 이미 토큰을 발행했는데 오류 수정을 할 수 있나와 해결 방법을 알려주시면 정말 감사하겠습니다.

안녕하세요, 해당 건과 관련해서 일반적으로는 불가능하다고 말씀드려야 할 것 같습니다.
아래와 같은 경우에 가능합니다.

가정) A가 토큰T를 발행 후 B에게 송금, B가 토큰T 10개를 토큰T 컨트랙트로 송금함. A가 토큰을 회수하고자 함.

일반적으로 토큰을 소유한다는 개념은, 토큰의 컨트랙트 내의 _balances 라는 변수에
mapping(address => unt256) 형태로 매핑되어있습니다.
B에서 토큰T 10개를 토큰T 주소로 오송금했다는 것은 쉽게 설명드리면

_balance[address_of_B] -= 10
_balance[address_of_T] += 10

이와 같은 상태변화가 나타난 것 입니다.
이때, 이것을 관장하는 함수가 내부함수인 _transfer(from, to, amount) 함수가 되는데요.
내부함수이기 때문에, 외부에서는 호출이 불가능합니다.

이때, 해당 토큰을 소유하고 있지 않은 제 3자인 A가 토큰T에 접근해서 토큰T지갑에 있는 10개의 토큰T를 회수하는 방법이 있는데 이 함수가
transferFrom(from, to, amount) 가 됩니다.
즉 이 경우에는 A가 토큰T 컨트랙트를 호출해서 tranferFrom(tokenT address, address_of_A, 10) 의 함수를 실행해야 합니다.

문제는 이 transferFrom에서 from 주소(토큰T주소) 에서 to 주소(A주소)로 송금을 하려면
_allowances 라는 변수에서 이를 허용하는 값이 입력되어있어야 합니다.

_allowances 변수는 mapping(address, mapping(address, uint256)) 으로 정의된 변수로
첫번째 오는 값이 잔고를 보유하고있는 지갑주소
두번째 오는 값이 잔고를 transfer하는데 허용된 지갑주소
세번째 오는 값이 허용된 수량 입니다.

transferFrom 이라는 함수를 실행하시면 아래와 같이

function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
        _transfer(sender, recipient, amount);
        _approve(sender, msg.sender, _allowances[sender][msg.sender].sub(amount));
        return true;
    }

첫번째로 sender에서 recipient로 amount를 보내고
_approve라는 함수를 통해 sender가 트랜잭션을 수행하는 주소에 대한 _allowances를 amount만큼 뺴도록 되어있습니다.
여기서 sub는 SafeMath로 0 이하의 값을 받으면 revert가 발생하기때문에, _allowances에 할당된 잔고가 없기때문에 트랜잭션은 실패하게 됩니다.

따라서 제3자인 A가 tokenT 컨트랙트 내의 tokenT 10개를 회수하려면
_allowance[tokenT address][address_of_A] > 10 이어야 합니다.
이 조건이 만들어지려면 tokenT contract가 자기 자신에게 트랜잭션을 호출해서 A주소에 10이상의 allowance를 할당해 줘야합니다.

이는 컨트랙트에 해당 작업을 해주는 external 또는 public 함수를 미리 설정 하지 않은 이상 불가능하기때문에, 현재 상황에서는 불가능하다고 설명드렸습니다.

혹시나 이를 예방하기 위해, 토큰 발행자가 아래와 같은 withdraw 함수를 만들지 않는이상 출금은 불가능합니다.

function withdrawAnyToken(address tokenAddress, uint256 amount) public onlyOwner {
    IKIP7(tokenAddress).tansfer(msg.sender, amount);
}

좀 복잡하게 설명드린것 같기는 한데, 도움 되셨길 바랍니다. 감사합니다.

1 Like