Čo je zlé na atomárnych swappoch a ako im môžu pomôcť kanály, čo dôležité sa stalo v hard forku Constantinople a ako postupovať, keď nie je za čo platiť za plyn.
Hlavná motivácia každého odborníka na bezpečnosť – túžba vyhnúť sa zodpovednosti.
Osud bol milostivý, opustil som ICO skôr, ako som sa dočkal prvej nezvratnej transakcie, ale čoskoro som sa ocitol pri vývoji kryptoburzy.
Ja – rozhodne nie som Malych Kibalchish a jedno prísne pohľad stačí, aby som odovzdal všetky kľúče a heslá. Preto hlavný cieľ ako architekta bolo umiestniť žeravý štipček kryptoanalyzovania čo najďalej od mne drahých prvkov infraštruktúry.
Nie sú tvoje kľúče, nie sú tvoje problémy.
Staviame systém výmeny aktív a chceme vylúčiť medziľahlé uchovávanie týchto aktív u seba, ale musíme zabezpečiť bezpečnosť transakcie.
Môžeme vystúpiť ako sudca v sporných situáciách a vykonávať transakcie s peňaženkami, ktoré vyžadujú dva z troch podpisov: kupujúceho, predávajúceho a escrows.
Avšak, ak sa účastník úspešne napadne escrows, získa požadované dva podpisy.
Atomárny swap – schéma výmeny, kde garantom je smart kontrakt, ktorý povoľuje len čestné správanie.
Akoby v záhade o vlkovi, koze a kapuste môžeš konať iba podľa jedinej správnej stratégie a nesieš straty, ak od nej ustúpiš.
Len namiesto hladu zvierat zabezpečuje poriadok hash funkcia, v ktorej je tak ťažké nájsť kolíziu, že to ani nestojí za to začínať.
Krok prvý: záhada.
Predpokladajme, že Alisa v jedno krásne ráno chce preniesť Bobovi bitcoin za hŕstku „kryptojuánov“.
- Odhaduje nejaké veľké tajomstvo.
- Získa od neho hash.
- Prenesie bitcoiny na smart kontrakt, z ktorého môže získať peniaze Bob, ak predloží tajomstvo (hash z neho musí byť rovný tomu uvedenému v kontrakte).
- V prípade, že Bob si po svoje bitcoiny nepríde do večera, Alisa si ich môže vziať späť.
Krok druhý: návnada.
Do hry vstupuje Bob a prevádza „kryptoeurá“ na svoj kontrakt, ktorý je napísaný tak, že:
- Alisa si môže vziať „kryptoen“, ak predloží tajné číslo.
- Nie skôr ako do obeda Bob, ak sa Alisa neobjaví, si môže vrátiť zálohu.
Krok tretí: odhaľovanie v návnade.
Alisa prichádza po svoje peniaze a berie peniaze z kontraktu Boba, pričom odhaľuje svoj tajný plán.
Konečný krok: hádanka je rozlúštená
Transakciu vidí Bob a ostrým zrakom z nej vyberá tajomstvo, ktoré Alisa predložila v kontrakte. Toto tajomstvo využíva, aby získal svoje bitcoiny.
Keď niečo nejde podľa plánov
Ak sa Alisa náhle ukáže ako smrteľná, Bob si v obednú prestávku vezme svoje jüany.
Na oplátku Alisa večer vráti bitcoin, ak sa zradný Bob rozhodne zadržať peniaze na lepšie časy.
Ak uprednostňujete obrázok pred textom, na Habre pre vás je podrobnejšie a názorné .
Rozdiel medzi časovými limitmi je určený na ochranu pred zlomyseľnou Alisou, ktorá berie Bobove peniaze v poslednej možnej chvíli, pričom časový limit vyprší, zatiaľ čo on trasúcimi sa prstami zadáva hex do transakcie.
Účastníci nemôžu stratiť svoje peniaze, maximálne budú musieť čakať na vrátenie.
Podpora v blockchainsJe to jednoduchá schéma, ktorá si od interagujúcich blockchains vyžaduje len minimálne:
- Podpora smart kontraktov s aspoň jedným rozvetvením
- Oba blockhains musia podporovať rovnaké hashovacie algoritmy (nezabudnite skontrolovať dĺžku tajomstva)
- Časové zámky.
Na prvý pohľad už môžeme povedať burze "zbohom, naše stretnutie bolo chybou", ale tu to nie je také jednoduché.
Napriek všetkým svojim výhodám riešenia na atomický swap nemajú dostatočnú likviditu. Často preto, že v najpopulárnejšej dvojici BTC-USD fiátová časť nebola úplne tokenizovaná.
Úspech USDT vyvolal celú vlnu stablecoinov formátu ERC20 na akúkoľvek chuť, od custodialného USDC po algoritmický DAI.
Preto pre jednoduchosť hovoríme ďalej o tom, že Alisa predáva Bobovi bitcoiny za nejaké ERC20 tokeny a dúfame v úspech stabilizátorov, našťastie máme ešte veľa ďalších technických problémov.
Rýchlosť
Bitcoin a Ethereum a samostatne nie sú veľmi rýchle, a tu musíme najprv čakať na jeden vklad so všetkými potvrdeniami, potom na druhý.
To všetko je preto, že najprv peniaze vkladá účastník, ktorému je známe tajomstvo, a oponent čaká na ukončenie a až potom prevádza svoju časť.
Okrem toho sa zaoberáme veľmi volatilným aktívom, takže v tomto čase sa cena môže výrazne zmeniť, a zmeniť podmienky už nie je jednoduché.
Ochrana súkromia
Každá výmena zanecháva artefakty na oboch blockchainoch. Pozorný pozorovateľ si môže všimnúť rovnaké hashe v smart kontraktoch a urobiť logický záver, že prebehla transakcia, z čoho je možné udeliť množstvo záverov od kurzových po daňové.
Keď o tvojich záležitostiach vie burza — je to veľmi nepríjemné, keď to vie každý — je to dvakrát nepríjemné.
Použiteľnosť
Kľúč blockchainu vo všeobecnosti a Ethereu osobitne. Pozrime sa, aké kroky bude musieť podniknúť predávajúci a kupujúci.
Z pohľadu predávajúceho je to relatívne jednoduché: stačí jednoducho previesť bitcoin na p2sh adresu. S Ethereom je to oveľa zložitejšie.
ZmluvaPozrime sa na priemerný kontrakt z GitHubu pre swap:
contract iERC20 {
function totalSupply() public view returns (uint256);
function transfer(address receiver, uint numTokens) public returns (bool);
function balanceOf(address tokenOwner) public view returns (uint);
function approve(address delegate, uint numTokens) public returns (bool);
function allowance(address owner, address delegate) public view returns (uint);
function transferFrom(address owner, address buyer, uint numTokens) public returns (bool);
}
contract Swapper {
struct Swap {
iERC20 token;
bytes32 hash;
uint amount;
uint refundTime;
bytes32 secret;
}
mapping (address => mapping(address => Swap)) swaps;
function create(iERC20 token, bytes32 hash, address receiver, uint amount, uint refundTime) public {
require(swaps[msg.sender][receiver].amount == 0); // check is swap with given hash already exists
require(token.transferFrom(msg.sender, address(this), amount)); // transfer locked tokens to swap contract
swaps[msg.sender][receiver] = Swap(token, hash, amount, refundTime, 0x00); //create swap
}
function hashOf(bytes32 secret) public pure returns(bytes32) {
return sha256(abi.encodePacked(secret));
}
function withdraw(address owner, bytes32 secret) public {
Swap memory swap = swaps[owner][msg.sender];
require(swap.secret == bytes32(0));
require(swap.hash == sha256(abi.encodePacked(secret))); // swap exists
swaps[owner][msg.sender].secret = secret;
swap.token.transfer(msg.sender, swap.amount);
}
function refund(address receiver) public {
Swap memory swap = swaps[msg.sender][receiver];
require(now > swap.refundTime);
delete swaps[msg.sender][receiver];
swap.token.transfer(msg.sender, swap.amount);
}
}
Pozor! Nepoužívajte tento a iné kontrakty z článku v produkte, sú napísané výlučne na demonštráciu. Najmä tento.
- Bob musí zavolať na kontrakt tokenu metódu
approve, čím dá kontraktu swapu prístup k svojim tokenom - Bob vytvára swap a kontrakt pomocou metódy
transferFromzbiera na svoju adresu tokeny odosielateľa - Alice v
withdrawodhalí tajomstvo a zmluva vyžadujetransfer
Väčšina peňaženiek a kryptobúrz nepodporuje approve tokeny, a nie bez dôvodu.
Samotní používatelia často chybne prevádzajú tokeny na zmluvu, následkom čoho sa tokeny jednoducho strácajú. Komentáre na Etherscan sú plné nariekania nešťastných.
Na vyvolanie zmluvy je potrebné zaplatiť poplatok v ETH, čo znamená, že obidvaja účastníci musia mať pred začiatkom obchodu dostatok, čo väčšina nechce robiť.
Gazgolder
Na začiatok je dobré odstrániť kontrolu odosielateľa všade, kde je to možné, a predpokladať, že máme niekoho, kto trpí nadbytočným plynom a vyvoláva zmluvy pre všetkých záujemcov.
Modernizovaná zmluva
contract Swapper {
struct Swap {
iERC20 token;
address receiver;
uint amount;
address refundAddress;
uint refundTime;
}
mapping (bytes32 => Swap) swaps;
function create(iERC20 token, bytes32 hash, address receiver, uint amount, address refundAddress, uint refundTime) public {
require(swaps[hash].amount == 0); // use hash once
require(token.transferFrom(msg.sender, address(this), amount));
swaps[hash] = Swap(token, receiver, amount, refundAddress, refundTime);
}
function withdraw(bytes memory secret) public {
bytes32 hash = sha256(secret);
Swap memory swap = swaps[hash];
require(swap.amount > 0);
delete swaps[hash];
swap.token.transfer(swap.receiver, swap.amount);
}
function refund(bytes32 hash) public {
Swap memory swap = swaps[hash];
require(now > swap.refundTime);
delete swaps[hash];
swap.token.transfer(swap.refundAddress, swap.amount);
}
}
Zmluvno-kľúčový dualizmus a EIP 712
Ako vieme, adresa v éteri môže byť zmluvou, ale aj subjektom, teda kľúčom.
Hlavná úloha kľúča je podpisovať nejaké správy.
Môžeme použiť ako odosielateľa Bob-zmluvu, ktorá vykonáva všetky potrebné kroky, pričom predtým overí podpis Bobovho kľúča.
Teraz môže ktokoľvek sponzorovať poplatok účastníka, ale rozhodnutie prijíma len ten, kto pozná kľúč.
Bob-zmluva
library EIP712ProxyLibrary {
function hashCommand(address sender, iERC20 token, Swapper swapper, bytes32 hash, address receiver, uint amount, address refundAddress, uint refundTime) public view returns(bytes32);
}
contract ProxyBob {
address owner;
constructor(address _owner) public {
owner = _owner;
}
function createSwap(Swapper swapper, iERC20 token, bytes32 hash, address receiver, uint amount, address refundAddress, uint refundTime, uint8 v, bytes32 r, bytes32 s) public {
require(owner == ecrecover(EIP712ProxyLibrary.hashCommand(address(this), token, swapper, hash, receiver, amount, refundAddress, refundTime), v, r, s));
token.approve(address(swapper), amount);
swapper.create(token, hash, receiver, amount, refundAddress, refundTime);
}
}
Na prácu s podpismi komplexných štruktúr dát v Ethereum existuje štandard , podrobnejšie o ňom si môžete prečítať v
Rozdeľuj a panuj
Často scenár útoku na Ethereum kontrakt vyzerá takto:
- Účastník uloží prostriedky na kontrakt
- Potom si vezme prostriedky späť
- Niečo sa pokazí
- Útočník berie peniaze znova a znova
Ak sa vrátime k nášmu prvému príkladu, niečo sa pokazí, ak je záhadou prázdny zoznam bajtov.
Ako ukradnúť miliónVytvárame swap s hashom 0x66687aadf862bd776c8fc18b8e9f8e20089714856ee233b3902a591d0d5f2925
To je sha256 od 0x0000000000000000000000000000000000000000000000000000000000000000
Prenášame tajomstvo a berieme svoje tokeny
Prenášame ešte raz a berieme cudzie, všetko kvôli tomu, že 0 = 0
Vytvorením oddeleného kontraktu pre každú transakciu môžeme izolovať kontrakty na úrovni EVM.
Ale to nie je všetko: teraz má každá transakcia svoju adresu, na ktorú je možné poslať tokeny z akejkoľvek peňaženky alebo burzy.
Zanechané kontrakty a create2
Ale teraz pre každú transakciu musíme vytvoriť kontrakt a čakať, kým kupujúci prenesie tam svoj „kryptomenu“. V schéme „ráno kontrakty, večer peniaze“ vždy existuje riziko, že kupec odíde, a plyn na vytvorenie kontraktu už bol utratený.
Nedá sa urobiť tak, aby ráno peniaze a večer bajty?
V hardforku Constantinople vývojári pridali inštrukciu create2, ktorá vytvára nový kontrakt na determinovanej adrese
keccak256( 0xff ++ address ++ salt ++ keccak256(init_code))[12:]
Kde
- address — adresa továrenského kontraktu
- salt — nejaké číslo, ktorého význam sa dozvieme v ďalšej časti
- init_code — bajtový kód kontraktu a parametre konštruktora.
TovárňaInštrukcia funguje iba cez assembly, preto továrňa vyzerá trochu desivo:
contract Factory {
event Deployed(address addr, uint256 salt);
function create2(bytes memory code, uint256 salt) public {
address addr;
assembly {
addr := create2(0, add(code, 0x20), mload(code), salt)
}
emit Deployed(addr, salt);
}
}
Kód vášho kontraktu môžete získať pomocou web3:
const MyContract = new web3.eth.Contract(ABI, {})
const code = MyContract.deploy({
data: BYTECODE,
arguments: contructorArgs
}).encodeABI();
const factory = new web3.eth.Contract(FACTORY_ABI, factoryAddress);
tx = factory.methods.create2(code, salt);
Kvôli obmedzenej podpore v solidity môže byť plyn pre kontrakt nesprávne vypočítaný kvôli niektorým nuansám éteru.
Obzvlášť milé je, že v prípade nedostatku plynu kontrakt spadne s internou chybou, aniž by oznámil, že došlo k nedostatku plynu, čo by sa dalo očakávať.
Teraz môžeme prevádzať tokeny na zmluvy bez predchádzajúcej tvorby a pokiaľ ich nepublikujeme v sieti, nikto nebude mať tušenie, čo konkrétne robí zmluva.
Vrána vráne oči nevykúka.
Je jasné, že skutočného analytika, najmä toho, kto získal dobré investície na boj proti nepriateľom režimu praním peňazí, také detinské triky nezastavia, a po vytvorení zmluvy i tak uvidí hash.
Ako spraviť, aby hash nebol odhalený?
Samotný swap prenášame off-chain: účastníci si vymieňajú podpisy na prevod na swap-zmluvu a potom sa tajne odhaľuje tajomstvo.
Krok za krokom.Vytvorí sa dva "multisig", z ktorých je možné prevziať prostriedky pri súhlase Alicie a Boba.
Aby odchod do offline niekoho z účastníkov nebol tragédiou, pridáme staré dobré časové obmedzenie.
Alica a Bob paralelne vkladajú depozity.
- Alica si vymyslí tajomstvo a odovzdáva Bobovi hash tajomstva a podpis transakcie, ktorá prevádza bitcoiny na adresu swapu.
- Bob odovzdáva Alici podpis na vybratie tokenov na zmluvu swapu s vymysleným hashom.
- Alica informuje Boba o tajomstve.
V tomto momente nastáva harmónia: aj Alica, aj Bob môžu kedykoľvek ukončiť transakciu. V takej priateľskej atmosfére si môžu vymeniť podpisy na vybratie peňazí na konečné adresy.
Pre cudzího pozorovateľa to vyzerá, akoby peniaze prešli cez zmluvu s multipodpisom 2 z 2.
A takýto systém umožňuje obom stranám vykonať depozit súčasne, keďže tajomstvo sa vymýšľa až po všetkých potvrdeniach.
Level 2.
Keď môžeme vyberať peniaze na jednu adresu a nepublikovať medzičlánkovú transakciu, nič nám nebráni vyberať peniaze na viacero adries a uskutočňovať neobmedzený počet medzičlánkových transakcií. Nie je to nutný súbor pre výmenu, ale ak sa raz začne s výmenou, ťažko sa zastaví.
Teraz sa Alica a Bob môžu naplno rozbehnúť. Napríklad, automaticky počítať priemernú cenu, vymieňajúc podľa satoshi za sekundu, alebo jednoducho priamo spojiť market makera a príjemcu likvidity.
Krok za krokom.
- Predajca si vymyslí tajomstvo a odovzdáva kupujúcemu hash tajomstva a podpis transakcie, kde časť prostriedkov je prevádzaná na p2sh adresu swapu a zvyšok sa vracia na adresu predajcu.
- Zákazník prenáša podpis, ktorý umožňuje previesť tokeny a vrátenie na adresu príjemcu.
- Predajca odhaľuje tajomstvo
- História sa opakuje s novým tajomstvom, pričom sa k swapu a vráteniu pridáva aj prevod predtým zakúpeného na adresu zákazníka a už zaplateného na adresu predajcu.
Teraz máme prístup k vysokorýchlostnému p2p obchodovaniu, hlavným faktorom je sledovať čas a uzavrieť obchod pred uplynutím lehoty.
Avšak, s malými úpravami našich zmlúv môžeme našim kanálom darovať imortalitu, čo nám výrazne uľahčí vytváranie siete.
O tom však povieme v ďalšej sérii.
Zdroj: habr.com
