CK
https://etherscan.io/address/0x7a3684fa59984b074bf22efc16f7e29294b49803
Транзакция отправлена с адреса 0x7a3684fa59984b074bf22efc16f7e29294b49803
на нем куча перечислений без монет, только оплата газа, причём на один адрес, это не куча токенов как в описании,
вот сам контракт
https://etherscan.io/address/0x18d81d985d585405688ef7c62806152cf797ae37
создатель контракта
https://etherscan.io/address/0xc5b21f5b4cd84a1bac5b72ced9b19fe3bf895934
у этого контракта очень мало сработавших транзакций в основном ошибка выполнения и зависшие траназакции
https://etherscan.io/txs?a=0x18d81d985d585405688ef7c62806152cf797ae37&p=3
всего с несколько нормальных операций... последняя и приведена для примера
Входные данные при вызове этой транзакции
0xbdb056b3
0000000000000000000000005d3a536e4d6dbd6114cc1ead35777bab948e3643
00000000000000000000000025599dcbd434af9a17d52444f71c92987fa97cfc
000000000000000000000000a70960deb4f472340c2815d3be07e95c2631acc4
0000000000000000000000000000000000000000000005da23edc301a6400000
Что это за метод без ABI файла так сразу мне не узнать, но на вХоде всего 4 параметра, тоесть это транзакция вызова метода контракта,
но никаких транзакций непосредственного перевода токенов нет - всё что мы видим в эксплорере это только результат работы контракта.
Для контракта не опубликованы исходные коды, можно попробовать декомпиляцию, она не проходит корректно, но кое что видно
#
# Panoramix v4 Oct 2019
# Decompiled source of 0x18d81D985D585405688ef7C62806152Cf797ae37
#
#
def _fallback() payable: # default function
stop
def unknown8b418713(uint256 _param1, uint256 _param2, uint256 _param3, array _param4): # not payable
require calldata.size - 4 >=′ 128
require _param1 == addr(_param1)
require calldata.size - 36 >=′ 64
require _param2 == addr(_param2)
require _param3 == _param3
require _param4 <= 18446744073709551615
require _param4 + 35 <′ calldata.size
require _param4.length <= 18446744073709551615
require ceil32(_param4.length) + 192 <= 18446744073709551615 and ceil32(_param4.length) + 192 >= 160
require _param4 + _param4.length + 36 <= calldata.size
// проверка входящих параметров
mem[192 len _param4.length] = _param4[all]
mem[_param4.length + 192] = 0
// ПРоверка на возможность вызовов с определённых адресов
if addr(_param1) != this.address:
revert with 0, 'callFunction wrong sender'
if 0x1e0447b19bb6ecfdae1e4ae1694b0c3659614e4e != caller:
revert with 0, 'callFunction wrong msg'
mem[ceil32(_param4.length) + 196] = this.address
require ext_code.size(0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2)
// https://etherscan.io/address/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
// Вызов функци стороннего контракта Wrapped Ether (WETH)
static call 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2.balanceOf(address owner) with:
gas gas_remaining wei
args this.address
mem[ceil32(_param4.length) + 192] = ext_call.return_data[0]
if not ext_call.success:
revert with ext_call.return_data[0 len return_data.size]
require return_data.size >=′ 32
require 0, ext_call.return_data == 0, ext_call.return_data[4 len 28]
require _param4.length >=′ 96
require mem[192] == mem[204 len 20]
_13 = mem[224]
require mem[224] == mem[236 len 20]
_14 = mem[256]
require mem[256] == mem[268 len 20]
mem[ceil32(_param4.length) + ceil32(return_data.size) + 228] = mem[268 len 20]
// "Хитрые" таблицы ассоциативного поиска, возможно вида "ктото комуто должен"
if not ext_code.hash(0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2):
revert with 0, 'SafeERC20: call to non-contract'
if ext_code.hash(0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2) == 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470:
revert with 0, 'SafeERC20: call to non-contract'
mem[ceil32(_param4.length) + ceil32(return_data.size) + 292 len 96] = 0, mem[ceil32(_param4.length) + ceil32(return_data.size) + 228], 0, ext_call.return_datamem[ceil32(_param4.length) + ceil32(return_data.size) + 292 len 28]
call 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2.mem[ceil32(_param4.length) + ceil32(return_data.size) + 292 len 4] with:
gas gas_remaining wei
args mem[ceil32(_param4.length) + ceil32(return_data.size) + 296 len 64]
if not return_data.size:
if not ext_call.success:
revert with 0, 'SafeERC20: low-level call failed'
if _param2 > 0:
require _param2 >=′ 32
require _param3 == bool(_param3)
if not _param3:
revert with 0, 'SafeERC20: ERC20 operation did not succeed'
else:
mem[ceil32(_param4.length) + ceil32(return_data.size) + 324 len return_data.size] = ext_call.return_data[0 len return_data.size]
if not ext_call.success:
revert with 0, 'SafeERC20: low-level call failed'
if return_data.size > 0:
require return_data.size >=′ 32
require mem[ceil32(_param4.length) + ceil32(return_data.size) + 324] == bool(mem[ceil32(_param4.length) + ceil32(return_data.size) + 324])
if not mem[ceil32(_param4.length) + ceil32(return_data.size) + 324]:
revert with 0, 'SafeERC20: ERC20 operation did not succeed'
require ext_code.size(addr(_14))
call addr(_14).0x1e8bb609 with:
gas gas_remaining wei
args addr(mem[192]), addr(_13), 0, ext_call.return_data[4 len 28]
if not ext_call.success:
revert with ext_call.return_data[0 len return_data.size]
// Логика по декопимиляции мне не особо понятна,
// но это больше похоже на прокси для контракта 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2 чем собствено самостоятельный контракт
https://github.com/nachomazzara/SafeERC20
https://hack.aragon.org/docs/common_SafeERC20
=========================
ПОсмотрим подробнее этот контракт 0xc02aa - похож на обычный токен
https://etherscan.io/token/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
у него много держателей 70,122 addresses, и он торгуется на биржах
Для контракта 0xc02a, есть лог вызов метода разрешающего работать контракту 0x18d81 по его методам перевода токено
Approval (index_topic_1 address src, index_topic_2 address guy, uint256 wad)
Для него уже есть опубликованные коды
https://etherscan.io/address/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2#code
/**
*Submitted for verification at Etherscan.io on 2017-12-12
*/
// Copyright (C) 2015, 2016, 2017 Dapphub
pragma solidity ^0.4.18;
contract WETH9 {
string public name = "Wrapped Ether";
string public symbol = "WETH";
uint8 public decimals = 18;
event Approval(address indexed src, address indexed guy, uint wad);
event Transfer(address indexed src, address indexed dst, uint wad);
event Deposit(address indexed dst, uint wad);
event Withdrawal(address indexed src, uint wad);
mapping (address => uint) public balanceOf;
mapping (address => mapping (address => uint)) public allowance;
function() public payable {
deposit();
}
function deposit() public payable {
balanceOf[msg.sender] += msg.value;
Deposit(msg.sender, msg.value);
}
function withdraw(uint wad) public {
require(balanceOf[msg.sender] >= wad);
balanceOf[msg.sender] -= wad;
msg.sender.transfer(wad);
Withdrawal(msg.sender, wad);
}
function totalSupply() public view returns (uint) {
return this.balance;
}
function approve(address guy, uint wad) public returns (bool) {
allowance[msg.sender][guy] = wad;
Approval(msg.sender, guy, wad);
return true;
}
function transfer(address dst, uint wad) public returns (bool) {
return transferFrom(msg.sender, dst, wad);
}
function transferFrom(address src, address dst, uint wad)
public
returns (bool)
{
require(balanceOf[src] >= wad);
if (src != msg.sender && allowance[src][msg.sender] != uint(-1)) {
require(allowance[src][msg.sender] >= wad);
allowance[src][msg.sender] -= wad;
}
balanceOf[src] -= wad;
balanceOf[dst] += wad;
Transfer(src, dst, wad);
return true;
}
}
Рассматривать какие токены куда переводятся и по какой логике думаю смысла нет , попросили рассказать про транзакцию, а не про то что хотели придумать авторы создавая такого тяни-толкая 😉