{"version":"https://jsonfeed.org/version/1","title":"Nat Chin","home_page_url":"https://natchineth.com/","feed_url":"https://natchineth.com/feed.json","description":"A minimal hugo theme focus on content","favicon":"https://natchineth.com//assets/favicon.ico","expired":false,"author":{"name":"Calvin Tran","url":"https://natchineth.com/"},"items":[{"id":"c9c4690064ad5f38c7cb105bb3e66fe569e423a6","title":"When Bitwise NOT breaks Differential Tests","summary":"","content_text":"When you build your test suite to work for you, it really works.\nIn a recent engagement, I used differential testing to verify if two implementations of the same logic—one in Golang, one in Solidity—were actually identical. This was a perfect use-case for differential fuzzing - logic that looks the same, under manual review. But looks aren\u0026rsquo;t everything.\nTo find them, I built a \u0026ldquo;fuzzing harness.\u0026rdquo; Imagine a monkey smashing a keyboard, taking that random input, and feeding it to the equivalent program in Solidity and Golang. If the Go version succeed on the input but the Solidity version hates it (or vice-versa), the fuzzer errors.\nDiggin\u0026rsquo; into the code The goal was for these two implementations to be identical.\nGolang Original:\n// ensure MAP_ANONYMOUS is set and fd == -1 if (flags.val()\u0026amp;0x20) == 0 || fd != u64Mask() { addr = u64Mask() errCode = toU64(0x4d) // no error } Solidity Original:\nswitch or(iszero(and(flags, 0x20)), not(eq(fd, u64Mask()))) case 1 { addr := u64Mask() errCode := toU64(0x4d) } Eureka\u0026hellip;.or kind of At a high level, both codebases were intended to return 1 on their first lines, to enter the if/switch statement. Instead, the program produced two separate numeric outputs, which was miscalculated. The fuzzer had found a deviation in which one of the calculations uses a padded variable, causing a discrepancy.\nStep Golang Logic Solidity Logic Match? 1. Check Flags 31\u0026amp;0x20 ==0 -\u0026gt; 1 isZero(and(31, 0x20)) -\u0026gt; 1 ✅ 2. Equality Check ** fd == u64Mask() = 1 eq(18446744073709551551, u64Mask()) = 0000000000000000000000000000000000000000000000000000000000000000 ❓ 3. The NOT Result is already 1 1111111111111111111111111111111111111111111111111111111111111111 -\u0026gt; 0xff.ff ❌ *Note: Step 2 in Golang logic combines step 2 and 3 in one. This is why the result is already 1.\nWhat happened? In Golang, the result of the check is a literal 1. The logic is only a single bit - this is expected behaviour.\nIn Yul, the not() operator is applied bitwise. When the equality check eq(fd, u64Mask()) returned a 0, it was interpreted as 00...00. Applying the not() operator on the 32 byte word of zeroes, flipped every single bit.\nThe result in Solidity wasn\u0026rsquo;t a 1 - it was a 1111111111111111111111111111111111111111111111111111111111111111.\nBecause the Solidity code used a switch statement, which expected a result of 1, the control flow did not enter the branch. In Golang, the same path resulted in a 1, which ran the associated code. This resulted in the final result of both implementations to be mismatched.\nEvolution of the Fuzzer The fuzzer went through four distinct iterations:\nV0 (Sanity Check): - Simple success/failure check - if one version reverts with input, both must revert and vice versa. V0.5 (Error Matching): - Tightened constraints. If both versions fail, the error codes must match. V1 (Input Targeting): - Defined specific numeric ranges for inputs to ensure that the fuzzer could explore additional flows. V2 (Coverage Bumper): - Analyzed branch coverage of unit tests, and realized that this if statement had no coverage. I manually seeded the fuzzer with inputs that should trigger this statement. The fuzzer found the deviation in seconds Smart Dumb Monkey-Smashing-Keyboard I mentioned that fuzzing is like a monkey smashing a keyboard, but a \u0026ldquo;dumb\u0026rdquo; monkey uses input space inefficiently. If you\u0026rsquo;re testing liquidity pools or low-level masks, a random uint256 will almost always just trigger either the same happy paths already discovered, or generic \u0026ldquo;Balance too low\u0026rdquo; or more likely, a series of reverts that causes the fuzzer to get nowhere.\nA \u0026ldquo;Smart\u0026rdquo; Fuzzer (V2) uses directed input generation. By constraining the \u0026ldquo;monkey\u0026rdquo; to smash keys within specific numeric ranges (like values just above or below u64Mask), we maximize coveraged reached by the fuzzer.\nThis is the intersection of security research and development: knowing where the code is likely to have issues and guiding the tools to look there. It is highly improbable the fuzzer would have found this specific bit-flip on its own without those manual adjustments to the harness. It is also highly improbable that this bug would be found via manual review.\nLessons for the Road Logical vs. Bitwise: In Yul, always use iszero(x) for negation. Avoid not() unless you are actually manipulating bits. Stop and think: Focus on the areas your unit tests don\u0026rsquo;t reach. Use coverage reports as a gauge for where to target your fuzzer. Always Deterministic: Never ignore a failed test, especially if it\u0026rsquo;s only sometimes fails. If any test fails once, you\u0026rsquo;re likely sitting on a bug. Understand it. Investigate it. ","content_html":"\u003cp\u003eWhen you build your test suite to work for you, it \u003cem\u003ereally\u003c/em\u003e works.\u003c/p\u003e\n\u003cp\u003eIn a recent engagement, I used differential testing to verify if two implementations of the same logic—one in Golang, one in Solidity—were actually identical. This was a perfect use-case for differential fuzzing - logic that looks the same, under manual review. But looks aren\u0026rsquo;t everything.\u003c/p\u003e\n\u003cp\u003eTo find them, I built a \u0026ldquo;fuzzing harness.\u0026rdquo; Imagine a monkey smashing a keyboard, taking that random input, and feeding it to the equivalent program in Solidity and Golang. If the Go version succeed on the input but the Solidity version hates it (or vice-versa), the fuzzer errors.\u003c/p\u003e\n\u003ch3 id=\"diggin-into-the-code\"\u003eDiggin\u0026rsquo; into the code\u003c/h3\u003e\n\u003cp\u003eThe goal was for these two implementations to be identical.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eGolang Original:\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-golang\" data-lang=\"golang\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// ensure MAP_ANONYMOUS is set and fd == -1\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#00a8c8\"\u003eif\u003c/span\u003e \u003cspan style=\"color:#111\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#75af00\"\u003eflags\u003c/span\u003e\u003cspan style=\"color:#111\"\u003e.\u003c/span\u003e\u003cspan style=\"color:#75af00\"\u003eval\u003c/span\u003e\u003cspan style=\"color:#111\"\u003e()\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e0x20\u003c/span\u003e\u003cspan style=\"color:#111\"\u003e)\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e||\u003c/span\u003e \u003cspan style=\"color:#75af00\"\u003efd\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e \u003cspan style=\"color:#75af00\"\u003eu64Mask\u003c/span\u003e\u003cspan style=\"color:#111\"\u003e()\u003c/span\u003e \u003cspan style=\"color:#111\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \u003cspan style=\"color:#75af00\"\u003eaddr\u003c/span\u003e \u003cspan style=\"color:#111\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#75af00\"\u003eu64Mask\u003c/span\u003e\u003cspan style=\"color:#111\"\u003e()\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \u003cspan style=\"color:#75af00\"\u003eerrCode\u003c/span\u003e \u003cspan style=\"color:#111\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#75af00\"\u003etoU64\u003c/span\u003e\u003cspan style=\"color:#111\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e0x4d\u003c/span\u003e\u003cspan style=\"color:#111\"\u003e)\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e// no error\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#111\"\u003e}\u003c/span\u003e \n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003eSolidity Original:\u003c/strong\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#272822;background-color:#fafafa;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-solidity\" data-lang=\"solidity\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#00a8c8\"\u003eswitch\u003c/span\u003e \u003cspan style=\"color:#111\"\u003eor\u003c/span\u003e\u003cspan style=\"color:#111\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#111\"\u003eiszero\u003c/span\u003e\u003cspan style=\"color:#111\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#111\"\u003eand\u003c/span\u003e\u003cspan style=\"color:#111\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#111\"\u003eflags\u003c/span\u003e\u003cspan style=\"color:#111\"\u003e,\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0x20\u003c/span\u003e\u003cspan style=\"color:#111\"\u003e)),\u003c/span\u003e \u003cspan style=\"color:#111\"\u003enot\u003c/span\u003e\u003cspan style=\"color:#111\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#111\"\u003eeq\u003c/span\u003e\u003cspan style=\"color:#111\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#111\"\u003efd\u003c/span\u003e\u003cspan style=\"color:#111\"\u003e,\u003c/span\u003e \u003cspan style=\"color:#111\"\u003eu64Mask\u003c/span\u003e\u003cspan style=\"color:#111\"\u003e())))\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \u003cspan style=\"color:#00a8c8\"\u003ecase\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e \u003cspan style=\"color:#111\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#111\"\u003eaddr\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:=\u003c/span\u003e \u003cspan style=\"color:#111\"\u003eu64Mask\u003c/span\u003e\u003cspan style=\"color:#111\"\u003e()\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#111\"\u003eerrCode\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:=\u003c/span\u003e \u003cspan style=\"color:#111\"\u003etoU64\u003c/span\u003e\u003cspan style=\"color:#111\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e0x4d\u003c/span\u003e\u003cspan style=\"color:#111\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#111\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"eurekaor-kind-of\"\u003eEureka\u0026hellip;.or kind of\u003c/h3\u003e\n\u003cp\u003eAt a high level, both codebases were intended to return 1 on their first lines, to enter the \u003ccode\u003eif\u003c/code\u003e/\u003ccode\u003eswitch\u003c/code\u003e statement. Instead, the program produced two separate numeric outputs, which was miscalculated. The fuzzer had found a deviation in which one of the calculations uses a padded variable, causing a discrepancy.\u003c/p\u003e\n\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003eStep\u003c/th\u003e\n\u003cth\u003eGolang Logic\u003c/th\u003e\n\u003cth\u003eSolidity Logic\u003c/th\u003e\n\u003cth\u003eMatch?\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003e1. Check Flags\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003e31\u0026amp;0x20 ==0 -\u0026gt; 1\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003eisZero(and(31, 0x20)) -\u0026gt; 1\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e✅\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e2. Equality Check **\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003efd == u64Mask() = 1\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003eeq(18446744073709551551, u64Mask()) = 0000000000000000000000000000000000000000000000000000000000000000\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e❓\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e3. The NOT\u003c/td\u003e\n\u003ctd\u003eResult is already \u003ccode\u003e1\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003e1111111111111111111111111111111111111111111111111111111111111111 -\u0026gt; 0xff.ff\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003e❌\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\u003cp\u003e*Note: Step 2 in Golang logic combines step 2 and 3 in one. This is why the result is already 1.\u003c/p\u003e\n\u003ch3 id=\"what-happened\"\u003eWhat happened?\u003c/h3\u003e\n\u003cp\u003eIn Golang, the result of the check is a literal \u003ccode\u003e1\u003c/code\u003e. The logic is only a single bit - this is \u003cstrong\u003eexpected behaviour.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eIn Yul, the \u003ccode\u003enot()\u003c/code\u003e operator is applied \u003cem\u003ebitwise\u003c/em\u003e. When the equality check \u003ccode\u003eeq(fd, u64Mask())\u003c/code\u003e returned a 0, it was interpreted as \u003ccode\u003e00...00\u003c/code\u003e. Applying the \u003ccode\u003enot()\u003c/code\u003e operator on the 32 byte word of zeroes, flipped \u003cstrong\u003eevery single bit.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eThe result in Solidity wasn\u0026rsquo;t a \u003ccode\u003e1\u003c/code\u003e - it was a \u003ccode\u003e1111111111111111111111111111111111111111111111111111111111111111\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003eBecause the Solidity code used a \u003ccode\u003eswitch\u003c/code\u003e statement, which expected a result of \u003ccode\u003e1\u003c/code\u003e, the control flow did not enter the branch. In Golang, the same path resulted in a \u003ccode\u003e1\u003c/code\u003e, which ran the associated code. This resulted in the final result of both implementations to be mismatched.\u003c/p\u003e\n\u003ch4 id=\"evolution-of-the-fuzzer\"\u003eEvolution of the Fuzzer\u003c/h4\u003e\n\u003cp\u003eThe fuzzer went through four distinct iterations:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eV0 (Sanity Check):\u003c/strong\u003e - Simple success/failure check - if one version reverts with input, both must revert and vice versa.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eV0.5 (Error Matching):\u003c/strong\u003e - Tightened constraints. If both versions fail, the error codes must match.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eV1 (Input Targeting):\u003c/strong\u003e - Defined specific numeric ranges for inputs to ensure that the fuzzer could explore additional flows.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eV2 (Coverage Bumper):\u003c/strong\u003e - Analyzed branch coverage of unit tests, and realized that this if statement had no coverage. I manually seeded the fuzzer with inputs that should trigger this statement. \u003cstrong\u003eThe fuzzer found the deviation in seconds\u003c/strong\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"smart-dumb-monkey-smashing-keyboard\"\u003e\u003cem\u003eSmart\u003c/em\u003e \u003cdel\u003eDumb\u003c/del\u003e Monkey-Smashing-Keyboard\u003c/h3\u003e\n\u003cp\u003eI mentioned that fuzzing is like a monkey smashing a keyboard, but a \u0026ldquo;dumb\u0026rdquo; monkey uses input space inefficiently. If you\u0026rsquo;re testing liquidity pools or low-level masks, a random \u003ccode\u003euint256\u003c/code\u003e will almost always just trigger either the same happy paths already discovered, or generic \u0026ldquo;Balance too low\u0026rdquo; or more likely, a series of reverts that causes the fuzzer to get nowhere.\u003c/p\u003e\n\u003cp\u003eA \u0026ldquo;Smart\u0026rdquo; Fuzzer (V2) uses directed input generation. By constraining the \u0026ldquo;monkey\u0026rdquo; to smash keys within specific numeric ranges (like values just above or below u64Mask), we maximize coveraged reached by the fuzzer.\u003c/p\u003e\n\u003cp\u003eThis is the intersection of security research and development: knowing where the code is likely to have issues and guiding the tools to look there. It is highly improbable the fuzzer would have found this specific bit-flip on its own without those manual adjustments to the harness. It is also highly improbable that this bug would be found via manual review.\u003c/p\u003e\n\u003ch3 id=\"lessons-for-the-road\"\u003eLessons for the Road\u003c/h3\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eLogical vs. Bitwise:\u003c/strong\u003e In Yul, always use \u003ccode\u003eiszero(x)\u003c/code\u003e for negation. Avoid \u003ccode\u003enot()\u003c/code\u003e unless you are actually manipulating bits.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eStop and think:\u003c/strong\u003e Focus on the areas your unit tests don\u0026rsquo;t reach. Use coverage reports as a gauge for where to target your fuzzer.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAlways Deterministic:\u003c/strong\u003e Never ignore a failed test, especially if it\u0026rsquo;s only \u003cem\u003esometimes\u003c/em\u003e fails. If any test fails once, you\u0026rsquo;re likely sitting on a bug. Understand it. Investigate it.\u003c/li\u003e\n\u003c/ol\u003e\n","url":"https://natchineth.com/posts/nearly-slipped-away/","date_published":"28046-28-09T449:2828:00-04:00","date_modified":"28046-28-09T449:2828:00-04:00","author":{"name":"Calvin Tran","url":"https://natchineth.com/"}},{"id":"ba049a7b121f55bcd86172ec13d28bbfd5dde2fa","title":"Curvance Invariants Unleashed","summary":"","content_text":"Initially posted on Trail of Bits Blog: Curvance: Invariants Unleashed\n","content_html":"\u003cp\u003eInitially posted on Trail of Bits Blog: \u003ca href=\"https://blog.trailofbits.com/2024/04/30/curvance-invariants-unleashed/\"\u003eCurvance: Invariants Unleashed\u003c/a\u003e\u003c/p\u003e\n","url":"https://natchineth.com/posts/curvance-invariants-unleashed/","date_published":"30046-30-09T446:3030:00-04:00","date_modified":"30046-30-09T446:3030:00-04:00","author":{"name":"Calvin Tran","url":"https://natchineth.com/"}},{"id":"61e5fcc0ddf5dc739dd0b3a303a5d09b24846033","title":"The Ultimate Secure Wallet","summary":"","content_text":"Initially posted on State Channels Smart Contract: The Ultimate Secure Wallet\nSafety has always been a major concern in the cryptocurrency industry. Once in a while, we’ll see cryptocurrency exchanges get hacked for millions of dollars. The concern of security is among one of the top reasons why people are reluctant to get into the cryptocurrency space. At STK, the security and the safety of your assets is always our top priority. Instead of a traditional wallet, we made a choice to use the smart contract and payment channels for our app. Due to the security nature of these contracts, we have not pushed our contracts up to mainnet yet. They will be pushed on mainnet soon after auditing.\nStoring Crypto in a Wallet vs a Smart Contract A crypto wallet is always generated using a private/public key pair. In other words, when you sign up for a new address with something like MyEtherWallet, you will get a “safety package” — containing your private key that you should be keeping safe. With MetaMask, you would have the mnemonic with the 12 seed words. If you forget these, you lose access entirely to your account. If you accidentally make your private key accessible to someone else, this person has full control over your funds.\nA smart contract, on the other hand, is different. There is no explicit private/public key differentiation — the address of the contract is the contract’s public key, but the private key is never made available. Unlike a crypto wallet, a smart contract does what its assigned to do, through code. For instance, our STK-smart-contracts is set to interact with only STK tokens. If other ERC20 tokens are sent to the smart contract, they are lost. This contract does not accept ETH transfers — so, if a customer accidentally transfers Ether to the smart contract, our contract will explicitly refuse it and refund it back. The only thing a user would lose is the gas fees for execution of said operation. Our smart contract also specifies that only STACK and User’s address can settle a channel. The settle function controls the movement of STK Tokens through a payment channel. Due to the restriction of changing the state of the channel, once an IOU has been submitted to change the state of a channel, no one can control the refund or transfers of tokens except yourself. The cryptocurrency you own is completely within your control.\nTransactions are safer with state channels In the initialization of a state channel, there are a few addresses that we make use of:\nuser address: the address of the wallet in which your funds are stored. When a channel is settled and the funds are returned back to the user, the tokens/ETH will be returned to this address. signer address: the private and public key pair generated on your device for signing purposes* recipient address: the address of the STACK’s wallet. When a channel is settled, the IOU amount will be transferred to STACK. channel address: the address of your personal state channel. When you deposit funds, this is where your funds are stored.\nFor you to sign transactions, the app automatically generates private and public key pairs. All transactions (IOU’s) are signed with this private key. These are only ever used to sign transactions that are sent to the smart contract. STACK never interacts with your signer’s private key. Notice your signer’s key never holds funds. Its only purpose is to sign off-chain transactions. With the following setup, transactions are safer with state channels, because there is no single point of failure. No matter what tokens there are in our payment channel, the funds inside it are always safe. Even if STK’s backend or database fails or goes down, the user is in complete control of the funds within the state channel.\nNetwork Congestion Back in December of last year, when Cryptokitties was released officially, the sheer number of transactions on the Ethereum Network skyrocketed and caused complete congestion. A few people in the Reddit AMA asked about the effects of network congestion on our state channels.\nWe sign the IOU’s off chain with the signer’s public and private key pair. These do not need to interact with the network. When you decide to settle a channel, these transactions will be pushed on-chain. During the settle period, you have the option to transfer any unused tokens back to your address. Your transaction amount will also be transferred to STACK. In other words, the end user is not affected by congestion on the network. This is ultimately safer for customers, because they are not affected by the volatility and the ever-changing block times on the network. To read more about how the IOU and signing off-chain transactions work, check this out.\nIf you’re intrigued, feel free to check out our crypto beta demo located here: https://www.youtube.com/watch?v=Yhmjks3eFIA, where we go through a live purchase at a local coffee shop.\n","content_html":"\u003cp\u003eInitially posted on \u003ca href=\"https://medium.com/stk-token/state-channels-the-ultimate-secure-wallet-9a17da38bd77\"\u003eState Channels Smart Contract: The Ultimate Secure Wallet\u003c/a\u003e\u003c/p\u003e\n\u003chr\u003e\n\u003cp\u003eSafety has always been a major concern in the cryptocurrency industry. Once in a while, we’ll see cryptocurrency exchanges get hacked for millions of dollars. The concern of security is among one of the top reasons why people are reluctant to get into the cryptocurrency space. At STK, the security and the safety of your assets is always our top priority. Instead of a traditional wallet, we made a choice to use the smart contract and payment channels for our app. Due to the security nature of these contracts, we have not pushed our contracts up to mainnet yet. They will be pushed on mainnet soon after auditing.\u003c/p\u003e\n\u003ch3 id=\"storing-crypto-in-a-wallet-vs-a-smart-contract\"\u003eStoring Crypto in a Wallet vs a Smart Contract\u003c/h3\u003e\n\u003cp\u003eA crypto wallet is always generated using a private/public key pair. In other words, when you sign up for a new address with something like MyEtherWallet, you will get a “safety package” — containing your private key that you should be keeping safe. With MetaMask, you would have the mnemonic with the 12 seed words. If you forget these, you lose access entirely to your account. If you accidentally make your private key accessible to someone else, this person has full control over your funds.\u003c/p\u003e\n\u003cp\u003eA smart contract, on the other hand, is different. There is no explicit private/public key differentiation — the address of the contract is the contract’s public key, but the private key is never made available. Unlike a crypto wallet, a smart contract does what its assigned to do, through code. For instance, our STK-smart-contracts is set to interact with only STK tokens. If other ERC20 tokens are sent to the smart contract, they are lost. This contract does not accept ETH transfers — so, if a customer accidentally transfers Ether to the smart contract, our contract will explicitly refuse it and refund it back. The only thing a user would lose is the gas fees for execution of said operation. Our smart contract also specifies that only STACK and User’s address can settle a channel. The settle function controls the movement of STK Tokens through a payment channel. Due to the restriction of changing the state of the channel, once an IOU has been submitted to change the state of a channel, no one can control the refund or transfers of tokens except yourself. The cryptocurrency you own is completely within your control.\u003c/p\u003e\n\u003ch3 id=\"transactions-are-safer-with-state-channels\"\u003eTransactions are safer with state channels\u003c/h3\u003e\n\u003cp\u003eIn the initialization of a state channel, there are a few addresses that we make use of:\u003c/p\u003e\n\u003cp\u003euser address: the address of the wallet in which your funds are stored. When a channel is settled and the funds are returned back to the user, the tokens/ETH will be returned to this address.\nsigner address: the private and public key pair generated on your device for signing purposes*\nrecipient address: the address of the STACK’s wallet. When a channel is settled, the IOU amount will be transferred to STACK.\nchannel address: the address of your personal state channel. When you deposit funds, this is where your funds are stored.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eFor you to sign transactions, the app automatically generates private and public key pairs. All transactions (IOU’s) are signed with this private key. These are only ever used to sign transactions that are sent to the smart contract. STACK never interacts with your signer’s private key. Notice your signer’s key never holds funds. Its only purpose is to sign off-chain transactions.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eWith the following setup, transactions are safer with state channels, because there is no single point of failure. No matter what tokens there are in our payment channel, the funds inside it are always safe. Even if STK’s backend or database fails or goes down, the user is in complete control of the funds within the state channel.\u003c/p\u003e\n\u003ch3 id=\"network-congestion\"\u003eNetwork Congestion\u003c/h3\u003e\n\u003cp\u003eBack in December of last year, when Cryptokitties was released officially, the sheer number of transactions on the Ethereum Network skyrocketed and caused complete congestion. A few people in the Reddit AMA asked about the effects of network congestion on our state channels.\u003c/p\u003e\n\u003cp\u003eWe sign the IOU’s off chain with the signer’s public and private key pair. These do not need to interact with the network. When you decide to settle a channel, these transactions will be pushed on-chain. During the settle period, you have the option to transfer any unused tokens back to your address. Your transaction amount will also be transferred to STACK. In other words, the end user is not affected by congestion on the network. This is ultimately safer for customers, because they are not affected by the volatility and the ever-changing block times on the network. To read more about how the IOU and signing off-chain transactions work, check this out.\u003c/p\u003e\n\u003cp\u003eIf you’re intrigued, feel free to check out our crypto beta demo located here: \u003ca href=\"https://www.youtube.com/watch?v=Yhmjks3eFIA\"\u003ehttps://www.youtube.com/watch?v=Yhmjks3eFIA\u003c/a\u003e, where we go through a live purchase at a local coffee shop.\u003c/p\u003e\n","url":"https://natchineth.com/posts/the-ultimate-secure-wallet/","date_published":"31076-31-09T740:3131:00-04:00","date_modified":"31076-31-09T740:3131:00-04:00","author":{"name":"Calvin Tran","url":"https://natchineth.com/"}},{"id":"aa8807fb27cc59a42904caaca453f73d04cf55ce","title":"DeltaHacks Interview","summary":"","content_text":"Initially posted on Software Hamilton\n","content_html":"\u003cp\u003eInitially posted on \u003ca href=\"https://softwarehamilton.com/2018/01/11/interview-deltahacks-iv-natalie-chin/\"\u003eSoftware Hamilton\u003c/a\u003e\u003c/p\u003e\n","url":"https://natchineth.com/posts/deltahacks-interview/","date_published":"11016-11-09T123:1111:00-04:00","date_modified":"11016-11-09T123:1111:00-04:00","author":{"name":"Calvin Tran","url":"https://natchineth.com/"}}]}