<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>jambestwick</title>
        <link>https://paragraph.com/@vatalikbuterin</link>
        <description>#FullStack Dev
build at 
 https://vfat.tools 
ETC China App Team Leader of RoadPark</description>
        <lastBuildDate>Mon, 27 Jul 2026 11:29:25 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <image>
            <title>jambestwick</title>
            <url>https://storage.googleapis.com/papyrus_images/d0cee501cb0c1c00a8f0b1f6e8a3a47e864c74ba52599c104e22f0298582cac9.jpg</url>
            <link>https://paragraph.com/@vatalikbuterin</link>
        </image>
        <copyright>All rights reserved</copyright>
        <item>
            <title><![CDATA[最长封锁160天，这些城市几乎被遗忘了]]></title>
            <link>https://paragraph.com/@vatalikbuterin/160</link>
            <guid>ky6iNgZGzTj8HiIaWEEq</guid>
            <pubDate>Mon, 25 Apr 2022 07:12:25 GMT</pubDate>
            <description><![CDATA[文|一条 为防控境外输入疫情， 我国的边境小城正陷入一场漫长的封锁。 截至2022年4月下旬， 云南的瑞丽，断断续续封城160天； 黑龙江的绥芬河，已经封城近90天； 广西的东兴，持续封城60天。疫情下的边境小城生活（摄影：斌先生） 根据全民核酸筛查人数对比推算， 疫情爆发以来，约有20万人离开了瑞丽， 近10万人离开了东兴…… 这些数字背后， 是一个个小人物的命运， 和一个个普通家庭的生计。 当原本平静的生活秩序被打破， 有人被迫转行、出走他乡， 有人困守原地、寻求出路。 由于地处边境，这些口岸城市一度有着 极为包容的文化和发展机遇， 但城市体量小、人口少，资源有限， 封锁带来的困境，鲜少被人看到。摄影：斌先生 一条找到这些深受封城之苦的居民， 和他们聊了聊封锁中的日常， 他们也需要帮助、鼓励和安慰。 当大多数目光都聚焦在上海， 我们希望这些边境城市的现状被更多人看到， ——希望他们，和他们的家园， 不要被真的遗忘。 撰文 陈沁、洪冰蟾、周天澄 责编 陈子文 摄影：斌先生2021年7月底，瑞丽第4和第5次封城的间隙，李尚排了5个小时队，终于申请到“离瑞证明”。他从市政府大楼跑回...]]></description>
            <content:encoded><![CDATA[<p>文|一条</p><p>为防控境外输入疫情，</p><p>我国的边境小城正陷入一场漫长的封锁。</p><p>截至2022年4月下旬，</p><p>云南的瑞丽，断断续续封城160天；</p><p>黑龙江的绥芬河，已经封城近90天；</p><p>广西的东兴，持续封城60天。</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/59841a497938f92eb27d980416456178bbe2428a79669a9433390bf74f4afde9.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>疫情下的边境小城生活（摄影：斌先生）</p><p>根据全民核酸筛查人数对比推算，</p><p>疫情爆发以来，约有20万人离开了瑞丽，</p><p>近10万人离开了东兴……</p><p>这些数字背后，</p><p>是一个个小人物的命运，</p><p>和一个个普通家庭的生计。</p><p>当原本平静的生活秩序被打破，</p><p>有人被迫转行、出走他乡，</p><p>有人困守原地、寻求出路。</p><p>由于地处边境，这些口岸城市一度有着</p><p>极为包容的文化和发展机遇，</p><p>但城市体量小、人口少，资源有限，</p><p>封锁带来的困境，鲜少被人看到。</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/8ef50cb2a8cb1b01a91b8a51f0ec1349c3ea9cea6d75303a6759e0534d139313.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>摄影：斌先生</p><p>一条找到这些深受封城之苦的居民，</p><p>和他们聊了聊封锁中的日常，</p><p>他们也需要帮助、鼓励和安慰。</p><p>当大多数目光都聚焦在上海，</p><p>我们希望这些边境城市的现状被更多人看到，</p><p><strong>——希望他们，和他们的家园，</strong></p><p><strong>不要被真的遗忘。</strong></p><p><strong>撰文 陈沁、洪冰蟾、周天澄</strong></p><p><strong>责编 陈子文</strong></p><p>摄影：斌先生</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/34a50baaf6891030a2d7098151292f9c7743587b425c99b83a7e45a4b7997326.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/f7c9bd06e7cb3985b71d1ec9216eee27d3d90b3eba4008ada9541d3074eeff79.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>2021年7月底，瑞丽第4和第5次封城的间隙，李尚排了5个小时队，终于申请到“离瑞证明”。他从市政府大楼跑回住处，胡乱抓了手机、钱包、身份证和几件随身衣物，然后头也不回地驾车驶离瑞丽。</p><p>他在这个边境小城生活了8年，离开却只用20分钟。“拿到这个证必须24小时之内离开，不然就作废了。我心里有很深的眷恋，但那时只想逃离。”</p><p>中午的阳光刺眼，快到出城的卡口，车流开始拥堵，排起长队。李尚忍不住紧张起来，虽然手续齐全，有48小时内的双检双采报告（离瑞要求在两个检测机构，分别自费完成口和鼻咽拭子，并间隔24小时），但他仍担心一道道检查，随时请他原地掉头。</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/b639cd6bc4592c63eb03140f129bd9add62b4cada444993ea1f575b21259f785.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>昔日的瑞丽街头（摄影：悠游云南）</p><p>李尚今年40岁，2014年他来瑞丽租了一栋楼做青旅，又按揭买了一套自住的房子，就这样结束了十年的漂泊生活，把这里当作自己的“第二故乡”。</p><p>瑞丽三面接壤缅甸，边境线长达169.8公里，进出口贸易繁荣，生活节奏又不紧不慢。在李尚看来，这里是一个包容又充满机遇的地方。当地的傣族和景颇族人淳朴善良，缅甸、泰国、印巴人，还有全国各地的移民带来了多元的文化和美食。封城前，青旅最低的入住率也有60%，他原本计划在缅甸再开一家分店。</p><p>2021年3月31日封城后，因为家在封控区，李尚无法回家，只能住在店里。依靠之前囤的物资和联系骑手送菜，他能勉强维持日常生活。虽然不断听到政府发放生活物资的消息，但李尚只收到过一次，是一份凉茶。物价涨了不少，原本一斤8块左右的小米辣，后来涨到近40块。</p><p>更让他发愁的是生意，没有旅客能进入瑞丽，他也无法开门营业，店里的缅甸工人都离开了。 在长达4个月的时间里，旅店里只有他一个人，呆在空荡荡的房间里，唯一能做的事就是做核酸，然后“等希望一点点磨没。”</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/bd985a7a67e2872b45215aaeed2b1d4466e14f30efa3ce3ebec1fa4b53da4e82.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>封锁后，空无人迹的瑞丽街头</p><p>李尚周围的朋友，几乎都选择离开瑞丽，以前喊一声就在宵夜摊上见面的人们，如今各奔东西谋求生路。</p><p>到如今，瑞丽已经断断续续封城一年，有时是封控管理，有时是居家隔离，有时是居家休息。从3年前疫情爆发开始，瑞丽市民已经经历9次封城，时间超过160天，前后至少130次核酸。</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/bc3b1db863ccc2bce85d769686d86ef8c98b46c2a9b39730a148b5279f9c738d.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>瑞丽城区居民封城时间记录</p><p>根据瑞丽官方发布的数据，最近的一次全民核酸检测（2022月4月18日）约有19万人，而一年前的核酸检测（2021年4月13日）约有38万人。这意味着在这一年里至少有20万人离瑞。</p><p>玉石商人刘珊珊还记得最开始做核酸，得排40多分钟的长队，前几天她下楼直接就能做上。她居住的楼层共有6户，在过去的一年里，他们陆续搬走，如今只剩下她一家还会在夜晚亮起灯。</p><p>原本繁荣的玉石交易、进出口贸易、旅游业和餐饮业几乎停摆。姐告边境贸易区的封锁是突然发生的。付了年租金的铺面，去年一年，刘珊珊只摆了不到一个月。封城最严格的时候，即使有老客人找上门，他们也无法从缅甸拿货，无法从瑞丽发货。到了去年5月4日，姐告解封。再过3个月，除了防疫人员，所有人被要求撤出姐告，那里成为“无人区”。</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/ba875ee4e948d7a501e6ece0f71db02b4a28eac4c6f6edb806117f62f3ddfde5.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>姐告是国内最大最早的玉石市场，陆地跟缅甸的木姐相连，经由姐告大桥与瑞丽市区隔江相望</p><p>刘珊珊时常接到小姐妹的电话，告诉她要离开的消息，然后便是哭泣声。</p><p>有人去广东继续做玉石生意，有人回老家，有人彻底改了行，卖菜、卖酒、做骑手，有人为了孩子读书搬到临近的城市。瑞丽多数中小学，除了高三，长达一年没有复课。孩子每天在家上网课，有时师生比是惊人的1:800。</p><p>在瑞丽，夜不能寐的人是很多的。刘珊珊总是失眠，发愁债务，纠结要不要离开。她来瑞丽16年，在姐告和城区分别租了一个铺面卖玉石。姐告的米柜有两米长，一年租金2万4，转让费4万，城区的租金一年2万，做生意贷款了15万，刚刚还掉4万多，明年得还完剩下的十几万。车贷刚刚还完，房贷每个月要6千多块。</p><p>“9次封城，我都是一个人在家里，最长的一次待了28天。楼对面有一个人，每天都嘶吼宣泄。”</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/5b9ede459c913c18f866cb15cf661d20be71c3431cb9f07a4ba82a2dfe7cdcb0.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>人们关在家里的时候，油桐花已经开得很好了</p><p>3月24日开始，住在低风险区的瑞丽市民可以出门了。刘珊珊骑车上山去兜风。以前她会约几个朋友，一起骑车去芒市，到那儿累得直接瘫倒，再吃得饱饱的，那种日子是那么幸福，如今只剩下她一个了。</p><p>她不是没想过离开，但在瑞丽的房贷、房租，没有任何缓交、补贴的解决方案，离瑞一度规定不能携带生产经营资料，这意味着玉石商人得把身家留在原地。去陌生城市做生意，又需要一笔资金投入。“有谁是真的愿意离开啊？我们已经在这里扎下根，突然要去一个新的地方，我是真的害怕。”</p><p>刘珊珊身边的朋友，很多都靠几张信用卡维持着。偶尔做几单生意，一张卡套一张卡，借网贷的也不在少数。她自己也过得紧巴巴。“一听牛肉要60一斤，我都没敢买。像榴莲和樱桃，我连吃的欲望都不敢有。”她不知道这样的日子何时能有转机，甚至不敢对未来有什么期望。</p><p>李尚如今在云南另一个城市租了房子，转行做茶叶生意，赚来的钱除了日常生活开销，还要支付瑞丽那一间至今无法进入的房子的贷款。他说这一切像是“马尔克斯的小说”，人到中年，他又开始新的漂泊。</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/929fc14e343168a4f1693ac178154fcef2686b7821edc779ce289cfd6479c0ed.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>封城进入50天后，广西东兴市人的朋友圈里，一个视频流传开来：一个中年男人，正在抱头痛哭，连续50多轮核酸检测，已经让他濒临崩溃。</p><p>情绪像决堤的洪水，吞噬着每一个观看视频的当地人，他们理解那种溃败感。自2020年初疫情爆发以来，这是东兴市最漫长的一次封锁，等待的人们，不知何时是尽头。</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/a627fdb45b991ee15fe976155d313747b8e3719a0095ad7d7b5a7b94b51289f3.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>摄影：斌先生</p><p>今年2月23日晚上，四川人古月先觉察到异样，因为在东兴口岸做中越贸易，她平日需要发很多快递，所以“消息更灵通一点”，她发现所有物流都停了——入夜的东兴市，悄无声息地封了城。</p><p>古月是四川移民，在东兴已是第六个年头。在东兴口岸，她主要做越南特产的生意，卖榴莲饼、盐焗腰果、咖啡和旅游纪念品，有两个孩子要养活。</p><p>东兴口岸不大，和越南仅隔着一条北仑河，一座111米长的桥跨越其上，连接着两个国家。以前，她站在商铺门口，能看到对岸的越南人打篮球。</p><p>县级市东兴，行政上归防城港市管辖。按过去的数据，这里有20万左右的常住人口，其中超过15万是外地移民。旅游业、中越贸易及相关产业是支柱，大部分人赖此为生。</p><p>摄影：斌先生</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/936d4e2d1351d0312cd56a84b22d385519d666203ec4ba0ff587cc4e0e24f121.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>古月还记得2019年底的东兴口岸，“那一片特别灿烂”。过年的时候，到处人头攒动，大家都在忙碌着备货，如今只剩一片萧条。</p><p>印象里，东兴的街道上随处可见杨桃、香蕉、菠萝蜜和龙眼树，果实成熟的时候，空气里会有一种特别的甜香，这都是家乡四川看不到的景象，但她已经50多天没怎么出过门了（出门的机会，主要是做核酸）。</p><p>网格化管理后，整个小城分为有疫区和无疫区，一旦一栋楼里有阳性病例，会将整栋的居民拉去隔离。街道上早已空落，紧闭的卷帘门和灰扑扑的店招，仿佛泄露着这座口岸城市的暮气，在以往，它本充满活力。</p><p>封锁带来的生存问题，都很具体。虽然能通过“群接龙”的方式买到菜，但物价涨得厉害，原来2块钱一斤的青菜，现在要7块钱。跑腿费从最初的10块钱，上涨到20块。水果很难买，大人可以不吃，但作为母亲，她想让孩子吃到。一岁多的小朋友，还在用纸尿裤、喝奶粉，这些都是开支。古月一家五口人，极尽控制，以前最基本的生活开销要50块，现在“100块也打不住”。</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/1b7f52121825f76089be099fa7826149b8ff71b22a157eefb35d72fd639a0af2.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>封锁前夜晚的东兴街头（摄影：斌先生）</p><p>生活成本在上涨，但整个城市已停滞，大家无法出门工作，所有人面对最现实的问题，是经济上的困境。</p><p>古月的朋友，同在东兴口岸做生意的汕尾人柳现对此感触很深。有一次，他在自己的小区群里，看到一个储蓄用尽的人，在向社区申请“5斤大米，一小瓶花生油”——封城持续太久了，很多人生计无着。</p><p>在3月25日，柳现策划了自己的“出逃”，那是东兴封城的第30天。“刚好封了一个月，我看不到任何希望，就决定走了。”当时离开的政策，是自费在酒店隔离5天，每天的花费是100元，酒店环境极为简陋，但离开是他仅存的希望，他归心似箭。</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/3e530ca01b601f61e4140d78e4a0f8caa1b2acec1bb8ff9e609d3b295ae692d8.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>疫情期间的高速公路（摄影：斌先生）</p><p>柳现虽然回到了家乡，但留在东兴的，是积压在口岸商铺里价值十几万的库存，其中很多是保质期有限的越南食品。每每想到这些损失，他会彻夜难眠。</p><p>从最近一次东兴市全城核酸筛查数据推算，边境小城东兴，人口已不足7万人，这意味着，十几万外地人已陆续离开，但也有人无法离开。</p><p>萧萧很早就从湖南移民到东兴，在这里已经生活了二十多年，户口也落在了这里，东兴已是她的“第二故乡”。她从事广告传媒行业18年，做事雷厉风行，也古道热肠。</p><p>这次疫情开始后，她第一批报名参加志愿者，“起初大家是一腔热血，希望赶紧让这个事情过去”。但当封锁无止尽地持续下去，她也感到自己的热情在一点点耗竭。</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/b2aaddbdf9124d718b7e9231637fedd27bb8a04c982127f29fb47b9ecc94eb58.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>摄影：斌先生</p><p>志愿者做着最辛苦、最累的活儿，承受着几乎日均一次的核酸——春天的东兴，白天的气温有时逼近30℃——裹着不透气的大白服。“就像把你牢牢捆住，每个人都动弹不得”。</p><p>因为封城当晚，她身在郊区，没能赶回城区的家，和丈夫被封在了两地。也因此，生活上相对城区自由一些，当她站在家中天台，还能看到远处的田野与山峦，也聊算“疫情中的一点安慰”。</p><p>萧萧其实是个乐观的人，在最悲伤的时刻，也会尽量调节自己的情绪。但她也遇到一些非常急迫的事情，与她不在一处封锁的父亲，因为肺癌手术，只剩下一个肺，每天需要吃靶向药维持生命，但在封锁中，药吃完了该怎么办？一家人感到一筹莫展。</p><p>在东兴，普通人的生活仿佛变成了一场没有胜算的困局。在等来解封之前，每一个人都在苦熬时间。</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/b8595ba16032d9c4bbde21a4ea176730d2800e7168055ed434481f81e777c089.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>绥芬河自今年的1月25日以来，封城已经断续持续了快三个月的时间，快递、药店、医院门诊全线停滞。对于2002年出生的市民小方来说，最大的痛苦还不是生活的不便，而是她失去了睡眠。</p><p>她有复杂的精神类疾病史，焦虑症和失眠症反复发作，她所需要的镇定剂和安眠药都面临断药的风险。“处境很为难，但是大家又普遍觉得，这好像不是什么了不起的急症，所以找不到任何开药的途径。”</p><p>她开始节约地吃药，从每天的服用到两天一服再到三天一服，最后实在是吃完了，失眠困住了她。“最严重的一次，四天三夜没有合过眼，困得快要背过气儿去了，但就是不能睡。那种感觉太痛苦了，人长期不睡觉，真的是会有生命危险的。”</p><p>长期的失眠同时诱发了严重的皮肤过敏。多病的她一直就这么挺着，直到最近几天，城市开始部分地复工复产，她才开到了药。</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/18a0d7ca8cd5f955d6563d2a930cf48f57d828d9f7b60f6faaf4caaf0b08166b.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>绥芬河的黄昏</p><p>小方是绥芬河本地人，因为身体原因，她选择了成为一位自由职业的设计师，可以远程办公，她留在了家乡这座黑龙江小城里。她说，这座城市人口不过十万有余，人人都是熟人，社交简单，生活方便，空气一直很好，是她心里的安全区。比起大城市，她更喜欢这里。</p><p>这里是边境城市，与俄罗斯接壤，1999年，这里设立了绥芬河中俄互市贸易区。小方的童年记忆里，绥芬河街头巷尾随处可见俄罗斯人，中小学也设有俄语课程。“一半以上的市民，家里多少会做点卖俄货的小生意。”</p><p>贸易繁荣的背景下，绥芬河虽小，一直显得颇有生机。城中有俄货一条街，售卖最受欢迎的俄式巧克力和饼干。</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/f1e70de8d3c0989de5dcb53ea497b7e97f3cd00bcd12faee5adb345c61b4474e.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>绥芬河俄货商店的巧克力（摄影：小盐粒儿）</p><p>2021年以来，这座边境城市在输入性病例前显得尤其脆弱。到了今年，断断续续几度封城，快递发不出也收不到。俄货一条街自疫情以来，已经倒闭了大半。</p><p>我们试着打通了几通俄货商店的店主电话，得到的反馈是无一例外的“这个不好做，店已经收了”或是“我已经不在绥芬河了”。一位大姐无奈又真诚地说，“店早就不开啦，你想买什么，我想办法帮你发一些。”</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/5d5cc063945bbe53c45dc26651faad39fb5cea1384ae20ee980f462d9222bea2.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>摄影：可爱小白龙</p><p>小方一直认为自己相比起这些要靠贸易为生的市民来说，算是“非常幸运的”。她家里囤货还算丰富，父母工作相对稳定，属于这座城市里受到影响较小的一批人。但即使如此，她也感觉到每一个家人都在封城里受困。</p><p>她母亲在学校工作。疫情发生的三年里，绥芬河市的中小学生几乎没有再重返过校园，所有的教学都在网课上完成——即使这座小城里的很多老师曾连电脑都不会用，大家努力维持对教学质量的要求。</p><p>母亲于是变得很忙，日常都要半夜两三点才能睡。老师们除了网课教学，还要去做核酸。绥芬河市封城的日子里，一度每天都需要全民核酸，医疗资源明显不足，所以核酸是需要各行各业的志愿者来完成的。</p><p>还有她的表姐，一位一线的志愿者，工作艰辛一言难尽。忙碌的时候连续工作14天，接触了密接之后以“14+7”的政策隔离。隔离的后七天，她住在没有装修好的家，既没有吃的、也没有通暖气，那是在边境严寒的冬天。</p><p>“我不知道她怎么捱过了这十四天，她实在是非常坚强的人。”隔离结束后，表姐直接又回到一线工作。</p><p>“这几个月，每个人情绪都非常不好，我经常和爸妈吵架，也时常听到楼上楼下吵闹的声音传过来。”</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/1045d745cc88f99ad03ef746646b8e6da47a2dda3582577536e2e6fe1b33e75d.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>绥芬河春天的晚霞</p><p>她曾经非常喜欢小城市彼此之间的亲厚，亲人朋友都住得很近，互相交流、照顾很方便。现在，她却看到一种连续性的痛苦。</p><p>不断有小道消息在传播，“几天后就解封”的信息给人希望，又不断破灭。</p><p>在这座藏不住消息的小城市，她常常听说因为没有收入来源、因为物价上涨而导致的冲突。</p><p>其间，绥芬河曾经短暂解封过三天，那三天里，小方看到许多人像“逃离丧尸病毒一样地”逃离了绥芬河。而就在那三天后，绥芬河又重新进入了封城状态。</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/90e1b5a95212d6bf3065fb4204e69ebd628eaa399d9e3063143b23ce8e1a80f6.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>夕阳西下穿校服的学生</p><p>相比起大城市如上海，疫情的相关信息还能被关注到，绥芬河这座老龄化严重的小城，鲜有声音可以出现在网络上，即使偶尔有，也很快会被众声喧哗所淹没。她觉得，这座深感其痛的城市，几乎已经被遗忘了。</p><p>这次，我们还联系到了一位当地的高三学生林林。高中三年，她仅有高一第一学期是在学校度过的，其他时间都在家里上网课。现在她在家备考，高考的志愿未定，但她已经想好，“我要离开这里”。</p><p>她最近的一条朋友圈是夕阳西下的学校，文案是“还是和大家在一起开心”。她是很乐观的人，和同学在那短暂的一学期里都建立了深厚的感情。她说，她能一定程度上理解封控的措施，但是对于缺位的高中三年，她还是感到非常遗憾。</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/043f1570927495e6eb80286d3e1c3ea3b5742b72d319b6f73b2a2abb65b3a8fe.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>绥芬河、瑞丽和东兴之外，还有更多这样的小城，正在承受着我们无法想象的压力。据不完全统计，3月下旬至今，全国至少有20多个城市陆续封城。</p><p>在这次上海疫情中，一条记录了很多无法忘却的时刻，为苦痛与温情，作微小的留存。上海之外，我们也希望这些被围困于疫情与封锁的小城，被看见、被记得。它们需要鼓励，需要帮助。</p><p>原文链接：<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://mp.weixin.qq.com/s/M-u3Ujb9qmtrJr5r11Mb1Q">https://mp.weixin.qq.com/s/M-u3Ujb9qmtrJr5r11Mb1Q</a></p>]]></content:encoded>
            <author>vatalikbuterin@newsletter.paragraph.com (jambestwick)</author>
        </item>
        <item>
            <title><![CDATA[分享-交易机器人（支持Binance、Coinbase、FTX永续合约等多种交易所）]]></title>
            <link>https://paragraph.com/@vatalikbuterin/binance-coinbase-ftx</link>
            <guid>Nax03RjeevShNNOyD9eg</guid>
            <pubDate>Thu, 14 Apr 2022 09:55:32 GMT</pubDate>
            <description><![CDATA[1.环境搭建对于小白来说，需要一些基础准备工作，一台Linux或mac的系统电脑，开发工具下载安装（webstorm或Visual Studio）Webstormhttps://www.jetbrains.com/webstorm/Visual Studiohttps://code.visualstudio.com/Git下载工具https://git-scm.com/2.准备工作做好，下载代码运行Crypto Trading Bothttps://github.com/jambestwick/crypto-trading-bot3.简单说明用于Bitfinex、Bitmex 和 Binance 等常见交易所的加密货币。由于大多数交易机器人只提供基本的买卖信号，因此它们提供了许多东西来获得利润，例如主要机器人不支持止损或止损限价等交易订单。也必须打破固定时间框架和技术指标的限制。特征充分利用 Websocket 进行交换通信，在市场上尽快做出反应一个实例中的多对支持sqlite3 存储蜡烛，股票行情，...网络服务器用户界面支持“做空”和“做多”信号对的浏览器仪表板Slack 和...]]></description>
            <content:encoded><![CDATA[<h2 id="h-1" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">1.环境搭建</h2><p>对于小白来说，需要一些基础准备工作，一台Linux或mac的系统电脑，开发工具下载安装（webstorm或Visual Studio）</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="" alt="Webstorm" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Webstorm</figcaption></figure><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.jetbrains.com/webstorm/">https://www.jetbrains.com/webstorm/</a></p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="" alt="Visual Studio" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Visual Studio</figcaption></figure><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://code.visualstudio.com/">https://code.visualstudio.com/</a></p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="" alt="Git下载工具" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Git下载工具</figcaption></figure><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://git-scm.com/">https://git-scm.com/</a></p><h2 id="h-2" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">2.准备工作做好，下载代码运行</h2><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="" alt="Crypto Trading Bot" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Crypto Trading Bot</figcaption></figure><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/jambestwick/crypto-trading-bot">https://github.com/jambestwick/crypto-trading-bot</a></p><h2 id="h-3" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">3.简单说明</h2><p>用于<strong>Bitfinex</strong>、Bitmex 和 Binance 等常见交易所的加密货币。由于大多数交易机器人只提供基本的买卖信号，因此它们提供了许多东西来获得利润，例如主要机器人不支持止损或止损限价等交易订单。也必须打破固定时间框架和技术指标的限制。</p><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">特征</h2><ul><li><p>充分利用 Websocket 进行交换通信，在市场上尽快做出反应</p></li><li><p>一个实例中的多对支持</p></li><li><p>sqlite3 存储蜡烛，股票行情，...</p></li><li><p>网络服务器用户界面</p></li><li><p>支持“做空”和“做多”</p></li><li><p>信号对的浏览器仪表板</p></li><li><p>Slack 和电子邮件通知</p></li><li><p>加入外汇蜡烛（例如，在 Bitmex 上使用移动速度更快的 Binance 交易/蜡烛进行交易）</p></li><li><p>TODO：显示可能的套利交易</p></li></ul><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">交易支持</h3><ul><li><p>具有杠杆配置的<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.bitmex.com/register/jS4mLN">Bitmex</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.bitmex.com/register/jS4mLN">Bitmex 测试网</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.binance.com/?ref=17569916">币安</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.binance.com/?ref=17569916">币安保证金</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.binance.com/en/futures/ref/302644">币安期货</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.coinbase.com/join/5a2ae60e76531100d3af2ee5">Coinbase Pro</a></p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.bitfinex.com/?refcode=kDLceRHa">Bitfinex</a>（保证金钱包）</p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.bybit.com/app/register?ref=46AK7">Bybit</a>杠杆配置</p></li><li><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://ftx.com/#a=1494781">FTX</a>（仅限永续合约）</p></li></ul><p>根据文档说明运行即可</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/a0898dbcc46ea6a3c8e485cbefba63ecc37cb7e23504d9bbf6f699956120306b.png" alt="Dashboard" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Dashboard</figcaption></figure><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/276bdfc25aab75b83d8b61a249162ca1a3986147589b8d33a67be0fe1b4db3d9.png" alt="Trades / Positions / Orders" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Trades / Positions / Orders</figcaption></figure><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/8120f665a2d9b235b2d78cdb816f53804437eaf5bbb591305281fb158f6ef1c3.png" alt="Backtesting
Currently there is a the UI for backtesting" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Backtesting Currently there is a the UI for backtesting</figcaption></figure><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/dad7730b68afbe9089786d77d3e8bb90e89f62dab394cf42e48ff654ad693ed2.png" alt="Manual Orders" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Manual Orders</figcaption></figure><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/ff4cd1ddb9dd5c69a40f2cb6430ea7bf32b9db0d936fc8652fbfd228f7294c7d.png" alt="Slack测试效果" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Slack测试效果</figcaption></figure>]]></content:encoded>
            <author>vatalikbuterin@newsletter.paragraph.com (jambestwick)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/a104dfea7aeb87164516995a1f216b4e26bf87d356126b2e11aebfaed24d8c9d.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[从冬奥双国籍冠军-谷爱凌到徐州锁链女-李莹，谈谈中国的阶层，社会]]></title>
            <link>https://paragraph.com/@vatalikbuterin/DDHTBZ0ra8jIBfb185Y1</link>
            <guid>DDHTBZ0ra8jIBfb185Y1</guid>
            <pubDate>Sat, 19 Feb 2022 15:55:04 GMT</pubDate>
            <description><![CDATA[今天又看到徐州被拐卖的事件，有两名女孩去丰县声援后，被刑拘了，后来放出来了。但通过本人发的图片，清楚看到了这个社会残酷，统治阶层的凶残。 图片来源徐州丰县被拐卖锁链女的声援者 事件：事件源于本来地方电台，采访想反映一个父亲抚养8个小孩的感人故事，但电台和政府万万没想到，当代网络的力量、就因为这一个采访会最终牵扯出人口拐卖，强奸，非法监禁，以及就此事当地的政府、警察不断遮掩，想淹没此事，以及逐渐被网络放大，刺激到每个有良知人的神经的故事。 简直现实版的《盲山》，甚至比电影还要冰冷残酷、该女子被通过暴力手段或是诱骗手段被弄到徐州-丰县的一个偏远的村子里，为什么被弄到这个地方，原因很简单，偏远的地方男人需要娶老婆，但问题是根本没有女人愿意去这样的贫穷地方生活，就算是本地长大的女人也希望去更好的城市生活。于是李莹就被百般的蹂躏，强奸，轮奸，在这个小村生了8个孩子，当地民政部门还为其颁发了《结婚证》，丈夫为了防止她逃跑，用铁链将其锁在一个冰冷的棚子里，冬天零下几度的天气可想而知人是怎么活着的。 图为被铁链栓住的8孩母亲杨女。当地政府的声明否认有拐卖行为，但事件及公告疑点重重，引发网民质疑。...]]></description>
            <content:encoded><![CDATA[<p>今天又看到徐州被拐卖的事件，有两名女孩去丰县声援后，被刑拘了，后来放出来了。但通过本人发的图片，清楚看到了这个社会残酷，统治阶层的凶残。</p><br><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/8656c82cf8e94f3d447654890b1518a793749861bd244bc2f083df44b26a44f8.jpg" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>图片来源徐州丰县被拐卖锁链女的声援者</p><p>事件：事件源于本来地方电台，采访想反映一个父亲抚养8个小孩的感人故事，但电台和政府万万没想到，当代网络的力量、就因为这一个采访会最终牵扯出人口拐卖，强奸，非法监禁，以及就此事当地的政府、警察不断遮掩，想淹没此事，以及逐渐被网络放大，刺激到每个有良知人的神经的故事。</p><p>简直现实版的《盲山》，甚至比电影还要冰冷残酷、该女子被通过暴力手段或是诱骗手段被弄到徐州-丰县的一个偏远的村子里，为什么被弄到这个地方，原因很简单，偏远的地方男人需要娶老婆，但问题是根本没有女人愿意去这样的贫穷地方生活，就算是本地长大的女人也希望去更好的城市生活。于是李莹就被百般的蹂躏，强奸，轮奸，在这个小村生了8个孩子，当地民政部门还为其颁发了《结婚证》，丈夫为了防止她逃跑，用铁链将其锁在一个冰冷的棚子里，冬天零下几度的天气可想而知人是怎么活着的。</p><br><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/627f6d1d8a1a1998632d87c60384853c7c0cb43696482f4bc0f987a3ef06b8c9.jpg" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>图为被铁链栓住的8孩母亲杨女。当地政府的声明否认有拐卖行为，但事件及公告疑点重重，引发网民质疑。（图：合成自微博）</p><br><p>在这里一直过了十来年，人的精神早已不正常，本来如果没有新闻媒体去采访，可能李莹永远就在这里这样生存，死去，没有人知道。但偏偏她的命运在2022年1月28日出现了转折，一名博主去这个所谓的“8个孩子”的父亲家里打卡，意外发现了有个女人被像动物一样锁着，出于好奇把图片发到了网上，一时间多名博主转载，点击量破亿，大家就‘这个女人是谁？是不是拐卖的，为什么铁链拴着？’等问题热议开来。</p><p>事情发酵后，徐州丰县分别在1月28日、1月30日及2月7日发出三份公告。</p><p>1月28日，中共丰县县委宣传部作出百来字的回应：否认有拐卖行为，强调视频中的女子杨某侠和乡民董某民是领证结婚，女子因有精神疾病和暴力倾向才被关在小屋。</p><p>后两则公告中，官方透露了更多关于杨某侠的个人信息，包括：杨某侠是云南省福贡县亚谷村人，原名小花梅；因语言行为异常，家属委托同村人带至江苏治病，随后杨某侠走失，但同村人并未报警，亦未告诉其家人。</p><p>公告中强调，公安机关已对董某民是否涉嫌违法犯罪开展调查，有关情况将适时公布。而中国的新华社与《人民日报》仅转述“徐州权威”的公告，并未对此作出评论。</p><br><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/d2bd3b306401042ea5c82ec0615944bd988a1de14108ca2ba82700739219b208.jpg" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><br><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/29423823f28296b6b5cb55b789ffa00a3ecd8d235b863965f76e6d788d0c5a10.jpg" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>同时本来地方政府和警察以为就这样发的信息发布会把舆论压下去，此事也就过去了，没想到事态发展超过了他们的想象，官方又承认了该女性是被拐卖的，导致徐州市，江苏省召开了常委会议要求彻查此事。</p><p>从该事件的一些人反应，可见这个当地风气的败坏。</p><p>丈夫，铁锁妻子，衣服单薄，只字不提，同时他透漏，他就喜欢孩子，不管孩子是谁的，都要养大，可见，该女子很有可能被轮奸过。</p><p>地方村委会：恶意的帮助董某民掩盖拐卖的老婆，协同其他村民封路，防止人逃跑，反映了中国人性的恶。</p><p>地方政府：未核实双方自愿，未取得双方身份证，颁发《结婚证》，已经是违法。</p><p>地方村民：拿董某当网红，拍照，宣传自己，或企业，全然没有怜悯思考的人性去管拐卖问题。</p><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">反观最近众星捧月的-谷爱凌的命运</h2><p>奥运冠军，富裕家庭出身，父亲业界号称google6号人物，妈妈，斯坦福MBA，投资机构合伙人高管，谷爱凌9岁拿到全美少年组冠军，斯坦福毕业，学霸+冠军，从小一路就是第一。这样的人生是很多人一辈子没发到达的高度，有人问她国籍问题：她回答：1、我的使命是通过体育把中美两国联系在一起，体育无国界；2、我也不打算浪费时间在没有受过足够教育的人身上。</p><p>从言语中透露着自信和傲气。</p><p>他们两个天堂地狱的人生，能说明很多问题，如果谷爱凌看到 徐州被锁女李莹这样这样的事件，不知道她还能不能说出那句‘受过足够的教育’，其实，人最无能为力的就是自己的出身，出身很大部分决定了你的教育，成长、医疗、选择、机会等等一些列人生的重要资源。</p><p>所以很多时候，高阶层的傲慢，和低层的愤怒是阶层的差异，见识认知意识形态的差异造成的，如果把她放到锁链女的人生，不知道她还能不能说出那些话来。</p><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">社会问题</h2><p>就拿我身边的一些人和事举个例子，身边有个工人阶层、靠打零工维持，有点钱就去赌博厅挥霍一把，和别人聊天，说美国霸权，到处侵略，自己就不假思索的认同，对贪官和有钱人也是，言语中透漏这憎恨。</p><p>有个局级干部，女儿在香港，夫妻两买了个很大的平层，隐姓埋名，钱哪来的大家懂得，教育女儿就是自己通过努力得来的这一切，女儿当然也就不认为他们贪污、受贿是违法的行为。</p><p>这就是教育。</p><p>中国几千年封建社会的教育把人洗礼的很彻底，人们信奉的是弱肉强食，从这点上来讲，就和人的文明思想背道而驰。</p><p>就像 高考，基本上中国不论是哪个阶层都很认可高考制度，为什么？1.相对公平，大家考试题目一致，至少省份一致，2.择优，录取按照分数从高到低，择优录取。这种选拔制度，是符合人性的，是能使绝大多数人服气的一种制度。你学习成绩差，考的不好，自然没人要，怨不得他人。别人成绩好，优秀，当然去好大学，大家并且赞赏。</p><p>就像一场比赛，赢得靠实力，输的也心服口服。</p><p>但是到了就业，发展，可有不是选拔制度了，尤其是这个社会统治阶层--公务员系统，大家都知道，中国的公务员能不能升迁，那是领导说了算，</p><p>这是任命制，任命制也有其有点，集权，效率高，但是，任命制有致命的缺点，那就是任命凭借上级喜好，任人唯亲，有才能的没法施展。这也是几千年封建王朝一直的根结所在。层层向上听命，整个社会走向集权，绝对的权利就会导致绝对的腐败，这里腐败不单纯是贪污，而是野蛮、横行、无度等等。</p><p>中国有个奇葩认知，就是打天下，所有人认为“天下是打下来的”，因此跟你做一个生意，开一家公司一样，谁做成了，那他就应该享受胜利的果实。可惜，中国的朝代更替已经一次次印证，这种草莽打下的天下，又会走向下一个轮回。中国人在意识形态里认为，谁得了天下，就拥有绝对的支配权，就像你的公司一样，这些打天下的人，世世代代的享受荣华富贵，但问题也就来了，你世世代代享受荣华富贵，势必有更多人世世代代要做奴隶，为你们服务，可是谁又愿意一直做奴隶呢？当外界条件达到一定程度，就要爆发，就是压制也压制不住了。</p><p>天下，就是是不是你靠“打”就能得到的私人财产？</p><p>我个人觉得不是，他应该是这个国家所有人，意志的一个集中表现，所以，我认为 天下应该是所有人“选”出来的。</p><p>中国人一边信奉，天下是打下来的，谁占有谁领导；一边忍受不了统治领导，要变革，要推翻。这不是很分裂吗？所以这种意识形态，和任命制是违背人性的。为什么公务员不能采用选举，选拔制呢？答案很清楚。</p><p>我个人觉得，选举制是优于任命制的，选举制，着重一个‘选’字，就是人人有权利选出自己认可的统治阶层，当然也可以是自己，统治阶层被选出来，对选举者也有所忌惮，这无形就是制约权利的一种方式，也就不会有任命制，集权这种很多事情发生。</p><p>就拿徐州丰县这件事来说，如果是选出来的一届党派统治下发生的，其他的在野党派就会拿此时大做文章，煽动民众情绪，逼其下台，单就事件本身来讲，被拐卖人口就是应该被营救，这是认知问题，促进了营救，增加惩处力度，营造良好社会风气。如果在野党上台，再发生这样那样，违背人心违背人性的事件，一样会被取代，但是问题是得到解决了，民众我不管你是什么执政，我有东西能制约，我能在一个相对公平，健康，进取的社会生存。而所谓把天下当成自己的私人财产，底层这些人的死活当然他不会放在心上，因为根本制约不了他什么，他只会想方设法的维护继续的统治，世世代代。</p><p>我个人浅显的认识，这就是中国朝代更替的怪圈。中国阶层的现象。</p><p>中国的阶层之间格格不入，阶层之间不会互相思考，其本质是和这个任命制，国家统治的制度有着千丝万缕的联系。</p>]]></content:encoded>
            <author>vatalikbuterin@newsletter.paragraph.com (jambestwick)</author>
        </item>
        <item>
            <title><![CDATA[一文读懂NFT的前世真生]]></title>
            <link>https://paragraph.com/@vatalikbuterin/nft</link>
            <guid>PVkR4EQrvDWS292i0lxe</guid>
            <pubDate>Fri, 18 Feb 2022 02:58:07 GMT</pubDate>
            <description><![CDATA[今天来讲讲NFT是什么，投机逻辑，商业价值什么是NFT NFT non-fungible token, 是存储在区块链上的不可互换的数据单元，是一种数字账本形式，可以出售和交易,不可分割，NFT被永久存储在链上，以TokenID作为一个NFT的编号,再详细的介绍，去看wiki，或者自己搜，多得是，在这不费口舌细讲了。 专业点来讲NFT是一种链上的加密资产，主要有3种协议，ERC721,ERC1155,ERC998 这三种协议均能生成NFT。 NFT发布有四个阶段：部署合约上链-→生成NFT-→生成图片动画等URL绑定NFT-→OpenSea 等NFT销售平台上架https://blog.csdn.net/JAVA_HHHH/article/details/120325604合约主要包含的一些函数方法：mint 初始化，就是将一个NFT生成出来，从00000000000地址生成到指定的用户地址。 function _mint(address to, uint256 tokenId) internal virtual { require(to != address(0), "ERC7...]]></description>
            <content:encoded><![CDATA[<h2 id="h-nft" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">今天来讲讲NFT是什么，投机逻辑，商业价值</h2><ol><li><p><strong>什么是NFT</strong></p><p>NFT <strong>non-fungible token,</strong> 是存储在区块链上的不可互换的数据单元，是一种数字<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://en.wikipedia.org/wiki/Blockchain">账本</a><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://en.wikipedia.org/wiki/Ledger">形式</a>，可以出售和交易,不可分割，NFT被永久存储在链上，以TokenID作为一个NFT的编号,再详细的介绍，去看wiki，或者自己搜，多得是，在这不费口舌细讲了。</p><p>专业点来讲NFT是一种链上的加密资产，主要有3种协议，ERC721,ERC1155,ERC998</p><p>这三种协议均能生成NFT。</p><p>NFT发布有四个阶段：部署合约上链-→生成NFT-→生成图片动画等URL绑定NFT-→OpenSea 等NFT销售平台上架</p></li></ol><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/1fecf1d8f22f9282c70573f278ec8ba3a17931fbb7dfa6dd4e3ecc96549460b4.png" alt="https://blog.csdn.net/JAVA_HHHH/article/details/120325604" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">https://blog.csdn.net/JAVA_HHHH/article/details/120325604</figcaption></figure><p>合约主要包含的一些函数方法：</p><ul><li><p>mint 初始化，就是将一个NFT生成出来，从00000000000地址生成到指定的用户地址。</p></li></ul><pre data-type="codeBlock" text="   function _mint(address to, uint256 tokenId) internal virtual {
        require(to != address(0), &quot;ERC721: mint to the zero address&quot;);
        require(!_exists(tokenId), &quot;ERC721: token already minted&quot;);
 
        _beforeTokenTransfer(address(0), to, tokenId);
 
        _holderTokens[to].add(tokenId);
 
        _tokenOwners.set(tokenId, to);
 
        emit Transfer(address(0), to, tokenId);
}
"><code>   <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">_mint</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> to, <span class="hljs-keyword">uint256</span> tokenId</span>) <span class="hljs-title"><span class="hljs-keyword">internal</span></span> <span class="hljs-title"><span class="hljs-keyword">virtual</span></span> </span>{
        <span class="hljs-built_in">require</span>(to <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>), <span class="hljs-string">"ERC721: mint to the zero address"</span>);
        <span class="hljs-built_in">require</span>(<span class="hljs-operator">!</span>_exists(tokenId), <span class="hljs-string">"ERC721: token already minted"</span>);
 
        _beforeTokenTransfer(<span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>), to, tokenId);
 
        _holderTokens[to].add(tokenId);
 
        _tokenOwners.set(tokenId, to);
 
        <span class="hljs-keyword">emit</span> Transfer(<span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>), to, tokenId);
}
</code></pre><ul><li><p>burn 销毁该NFT，必须是该NFT的持有者才能销毁该NFT</p></li></ul><pre data-type="codeBlock" text="  function _burn(uint256 tokenId) internal virtual {
        address owner = ERC721.ownerOf(tokenId); // internal owner
 
        _beforeTokenTransfer(owner, address(0), tokenId);
 
        // Clear approvals
        _approve(address(0), tokenId);
 
        // Clear metadata (if any)
        if (bytes(_tokenURIs[tokenId]).length != 0) {
            delete _tokenURIs[tokenId];
        }
 
        _holderTokens[owner].remove(tokenId);
 
        _tokenOwners.remove(tokenId);
 
        emit Transfer(owner, address(0), tokenId);
    }
"><code>  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">_burn</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> tokenId</span>) <span class="hljs-title"><span class="hljs-keyword">internal</span></span> <span class="hljs-title"><span class="hljs-keyword">virtual</span></span> </span>{
        <span class="hljs-keyword">address</span> owner <span class="hljs-operator">=</span> ERC721.ownerOf(tokenId); <span class="hljs-comment">// internal owner</span>
 
        _beforeTokenTransfer(owner, <span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>), tokenId);
 
        <span class="hljs-comment">// Clear approvals</span>
        _approve(<span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>), tokenId);
 
        <span class="hljs-comment">// Clear metadata (if any)</span>
        <span class="hljs-keyword">if</span> (<span class="hljs-keyword">bytes</span>(_tokenURIs[tokenId]).<span class="hljs-built_in">length</span> <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span>) {
            <span class="hljs-keyword">delete</span> _tokenURIs[tokenId];
        }
 
        _holderTokens[owner].remove(tokenId);
 
        _tokenOwners.remove(tokenId);
 
        <span class="hljs-keyword">emit</span> Transfer(owner, <span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>), tokenId);
    }
</code></pre><p>transfer，交换，就是将你的NFT发送给别人的地址</p><pre data-type="codeBlock" text="
    function _transfer(address from, address to, uint256 tokenId) internal virtual {
        require(ERC721.ownerOf(tokenId) == from, &quot;ERC721: transfer of token that is not own&quot;); // internal owner
        require(to != address(0), &quot;ERC721: transfer to the zero address&quot;);
 
        _beforeTokenTransfer(from, to, tokenId);
 
        // Clear approvals from the previous owner
        _approve(address(0), tokenId);
 
        _holderTokens[from].remove(tokenId);
        _holderTokens[to].add(tokenId);
 
        _tokenOwners.set(tokenId, to);
 
        emit Transfer(from, to, tokenId);
}
"><code>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">_transfer</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> <span class="hljs-keyword">from</span>, <span class="hljs-keyword">address</span> to, <span class="hljs-keyword">uint256</span> tokenId</span>) <span class="hljs-title"><span class="hljs-keyword">internal</span></span> <span class="hljs-title"><span class="hljs-keyword">virtual</span></span> </span>{
        <span class="hljs-built_in">require</span>(ERC721.ownerOf(tokenId) <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-keyword">from</span>, <span class="hljs-string">"ERC721: transfer of token that is not own"</span>); <span class="hljs-comment">// internal owner</span>
        <span class="hljs-built_in">require</span>(to <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>), <span class="hljs-string">"ERC721: transfer to the zero address"</span>);
 
        _beforeTokenTransfer(<span class="hljs-keyword">from</span>, to, tokenId);
 
        <span class="hljs-comment">// Clear approvals from the previous owner</span>
        _approve(<span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>), tokenId);
 
        _holderTokens[<span class="hljs-keyword">from</span>].remove(tokenId);
        _holderTokens[to].add(tokenId);
 
        _tokenOwners.set(tokenId, to);
 
        <span class="hljs-keyword">emit</span> Transfer(<span class="hljs-keyword">from</span>, to, tokenId);
}
</code></pre><ul><li><p>setTokenURI, 设置NFT令牌的URI(统一资源标识符)，简单来讲就是给这个NFT关联一个图片、动画等网络地址，如果该地址的图片被删了，NFT的图片也就展示不出来了。</p><pre data-type="codeBlock" text=" function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {
        require(_exists(tokenId), &quot;ERC721Metadata: URI set of nonexistent token&quot;);
        _tokenURIs[tokenId] = _tokenURI;
    }
"><code> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">_setTokenURI</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> tokenId, <span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span> _tokenURI</span>) <span class="hljs-title"><span class="hljs-keyword">internal</span></span> <span class="hljs-title"><span class="hljs-keyword">virtual</span></span> </span>{
        <span class="hljs-built_in">require</span>(_exists(tokenId), <span class="hljs-string">"ERC721Metadata: URI set of nonexistent token"</span>);
        _tokenURIs[tokenId] <span class="hljs-operator">=</span> _tokenURI;
    }
</code></pre></li><li><p>approve ,授权，就是你将你的NFT授权给其他人的地址，一旦授权给别人，他就能取走你的NFT了</p><pre data-type="codeBlock" text="    function _approve(address to, uint256 tokenId) internal virtual {
        _tokenApprovals[tokenId] = to;
        emit Approval(ERC721.ownerOf(tokenId), to, tokenId); // internal owner
    }
"><code>    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">_approve</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> to, <span class="hljs-keyword">uint256</span> tokenId</span>) <span class="hljs-title"><span class="hljs-keyword">internal</span></span> <span class="hljs-title"><span class="hljs-keyword">virtual</span></span> </span>{
        _tokenApprovals[tokenId] <span class="hljs-operator">=</span> to;
        <span class="hljs-keyword">emit</span> Approval(ERC721.ownerOf(tokenId), to, tokenId); <span class="hljs-comment">// internal owner</span>
    }
</code></pre></li></ul><p>NFT的操作基本就是这些，大多的项目团队，在做NFT时都会参考</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/contracts/token/ERC721">Open-zeppelin-ERC721</a>, 这些</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/3b2ffcca95f19d6ae56958d464fa66ed0121b0cdacc5565353c26b2edf38063d.png" alt="open-zeppelin，NFT库" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">open-zeppelin，NFT库</figcaption></figure><p>创建好合约以后，就可以部署了，部署到链上完成后，就可以开启售卖</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/87c78d5ce4ae4fcd7dec59a6dab4101d8990a14edc037493ee6613a9cc7c9ee2.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/2ac9797d6df792ee3225976eb587663ba82a3396c600ab3b408c62ab3c6a7eaa.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/d4363d09c7e2519413573970ee37c1b2c9557e3f44bab3baf22b8aab77a82df0.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>这就生成完NFT了，</p><p>现在有很多NFT盲盒项目，就是你生成NFT以后，不会马上看到自己的NFT图片长什么样，道理很简单，开发者将NFT的所有图片，放到一个地址集里，到指定的时间，将地址集里的图随件设置给所有的NFT，这样用户就提前看不到哪个NFT长什么样，或者mint的时候随机给一个图片地址，mint完成就能看到，这就是盲盒。</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/4f97f900b5e9932c29f528f991f3cef478517bbfe0fe8d6bbdfbe3222755a77f.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/cbe9a0430566919913c08bcc77350ae8029f9b98ac8f6467b50579eb4baec8d2.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>最后到OpenSea这类的NFT交易平台发布上架就可以了</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/88bd562c771ba723e3bd43b06494071be5f8b56a34513a1bc0465963d0ef3e8a.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>一个NFT就制作完成了，NFT相较于Defi合约更加简单，复杂度低，但开发者还是可以设置后门，这个得自己懂。</p><ol><li><p><strong>NFT的投机逻辑</strong></p><p>NFT相较于其他的代币或者Defi，Game类的项目，出圈度很高，任何人通过工具都能发行自己的NFT，NFT相当于一个藏品，尤其是歌星、影星、名流等发行NFT会有大量的粉丝群体为其买单，这些粉丝有别于币圈的投机者，疯狂的加一买卖；但粉丝忠诚度是比较高的，一旦买了，很可能就作为收藏，不卖了，也使得NFT价格上涨。</p><p>像球星内马尔、篮球 史蒂芬.库里 、亚洲的JJ 林俊杰、周杰伦、余文乐等等都购买过很多NFT，无形中吸引很多不懂币圈的外行人注意，吸引很多人的加入。</p><p>早年间的<strong>CryptoEggs、Blockheads、Cryptopunks</strong>等等的NFT项目存活下来的极少，基本上一波热度过去就消亡了。</p><p>NFT受众群体个人感觉有3类人</p><ul><li><p>资金体量较大的人或者机构、或者是明星、政要，他们购买NFT大多是为了娱乐，消遣，本身一个NFT的价格对他们来说九牛一毛。</p></li><li><p>粉丝、收藏者，粉丝和收藏者，这部分群体会跟随自己的偶像，或者看准哪个自己热爱的项目，比如自己从小看着日本《XX》动画片长大，有人发行了XX的NFT，他们就有意愿去购买。</p></li><li><p>炒币者，这类群体占到购买NFT的绝大多数，甚至90%以上，他们购买NFT目的只有一个为了转手，找人接盘，赚取差价。这也是币圈的风气，炒币者通过社群、关注推特、微博、Discord等社交软件，关注一些行内知名人士发布NFT消息，甚至有程序员做工具监控NFT的发布和交易量来监控热度，得到一手咨询、进行选择性购买NFT，并开始炒作，等达到合适价位，赶紧出手，赚取信息差价。</p><p><strong>但是NFT项目本身还是存在巨大风险和漏洞</strong>，比如:</p><p>1.NFT项目和其他的代币一样，任何人都能发行，没有监管，存在跑路的风险极高，人性是逐利的，大多数人一旦掌握一定的技术，就会发行NFT炒作，拉高价位，赚钱跑路，当然NFT项目大多也不需要升级功能和维护。</p><p>2.NFT开发者暗箱操作，自己通过多个账号不断购买抬高NFT地板价，自己只花取手续费，提高热度，吸引他人接盘。</p><p>3.NFT项目方通过预售，白名单、等等操作提前将低价位的一些少数名额，发放给社群大V，或者所谓的行业领袖、专家人士等，靠这些人进行推广炒作，部分这些人不负责任不去甄别项目的好坏、或者压根就不懂看合约、没能力鉴别，互相利用，吸引韭菜们接盘，存在诓骗，欺诈的行为。</p><p>4.NFT本身不像代币流动性极差，都是单一交易，也就是说，你的NFT如果没人看好，没人买，即使再低的价格，赔钱，也很可能就砸你手里，等热度一过，就真成了‘’纪念品‘’。</p><p>5.NFT开发者恶意留有后门程序，销毁合约，转移资产等操作，使得NFT持有者资产并没有保障。</p><p>6.欧美、日韩，尤其是日本的漫画师，插画师等，发现NFT炒作的商机，不断绘制，甚至拿出自己早年间不被认可的作品和项目方联合发行NFT，导致NFT相似度高，发行泛滥成灾，严重影响行业良性发展。</p><p>7.明星发行NFT，表面上看会有很好的粉丝效应，带动价格上涨，但仔细想想，明星周边的产品是很多的，可不止NFT一种，还有奶茶店、服装品牌、汽车、日用品等等，NFT可能是最不看好的一种，NFT跟这些实物纪念品甚至商品比起来，显然对粉丝是没有什么优势，粉丝买一件明星的衣服，天天穿，炫耀，和人还能聊相关的天，比NFT给心里的满足感更高，凭什么觉得粉丝一定会买NFT而不是明星代言的车来的更有价值。而且NFT可能都不是明星本人自愿发行，而是身边的经纪人为了迎合市场，炒作行为，明星都不关注的NFT，想想最后会是什么结果。</p><p>8.自诩聪明的炒币者，拿到白名单，低价生成NFT后，炒作，同时又出现多个大V关注度高热门的NFT项目，可能其他用户就转战其他更火的NFT项目，手上的NFT也就砸自己手里了，这样的项目数不胜数。</p><p>9.认为NFT白名单一定有人接盘、能赚钱的人，其实大概率是项目方的操纵，项目方发行10000个NFT，只推出10个名额，就算推出100个名额，也就只是1%的NFT，而这些名额，会有成千上万的人去关注，去做个人传销任务推广，能中的概率极低，存在朋友、社群暗箱操作给自己人名额，炒币者关注了项目，做了一些列任务，最后还不知道早就被暗箱操作，</p><p>项目方、行业大V白白收获大量的人气资源，还有韭菜们为其叫好。</p><p>对NFT项目来说这100个白名单名额，自己每个1ETH的买回去，100ETH也不算什么，这就是大多项目能让白名单用户赚点小钱的逻辑。</p><p>NFT是一个认知差、咨询差的产品，娱乐下就好，多数炒币者非技术出身、甚至没有多少基础常识，人云亦云，稀里糊涂的购买NFT，给别人接盘。</p></li></ul></li><li><p><strong>NFT的商业价值</strong></p><p>NFT与传统的收藏品、实物资产相比，非常便捷、查看度高、不可篡改，唯一标识身份等能力，任何人查看别人的NFT就能看到对方的资金体量，就像现实中有辆豪车，但是很多人不知道，但是通过高价的NFT就能证明自己的资金的实力，是一种身份的象征。因此很多人喜欢他，就像喜欢奢侈品一个道理，而且NFT本身的唯一性，注定了每个人的NFT与众不同。从技术层面讲，它本身和实物就完全不同，是互联网时代，分布式区块链时代的产物，因此才会收到人们追捧，因为大多数人认为，未来会是AI的时代，人们在现实和虚拟世界自由穿梭，人们在链上可以完成社交，建造，娱乐、购物等一系列的操作。</p></li></ol><p>总结：NFT的故事讲完了，区块链给了每个人一个公平的机会，任何人都可以发行，部署合约，靠多节点网络运行，在这个毫无约束的自由世界里，显然NFT作为标志是有其意义的，但同时行业乱象丛生，人性的野蛮在这里完全的释放，这可能就是事物的两面性吧。</p><p>如有任何问题: 可以互相交流：</p><p>wechat: 菜菜龙</p><p>twitter: jambestwick</p>]]></content:encoded>
            <author>vatalikbuterin@newsletter.paragraph.com (jambestwick)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/43a8a19cef382210b05ce98ff244851ad3291a76ee3ea3b25faf13b9d257f4aa.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[Web3缺少的还很多、很多]]></title>
            <link>https://paragraph.com/@vatalikbuterin/web3</link>
            <guid>GM0LM5oQMAoAAbtTSqFV</guid>
            <pubDate>Fri, 11 Feb 2022 10:26:12 GMT</pubDate>
            <description><![CDATA[Web3是一个入口，是接入blockChain的接口，是现实中的个体进入链上世界的桥梁，是未来的趋势。但是现在有些突出问题，制约着链上世界的发展。智能合约是以状态机改变驱动的，缺少大数据存储，索引查询机制arweave（AR）的存储基于链的开发，大的文件无法写入链上，单一全节点存储极大智能合约设计之初较为简单，没法满足现有强大的社交、媒体、多元化信息的需求缺少侧链接入ETH等链，融合多种信息大家都知道以太坊的智能合约只是交易，即从一个地址transfer到另一个地址，引发链上状态改变，产生费用，矿机打包收费，这样的经济模式，但是问题以太坊并未对存储做出对应的设计，存储的只有交易信息，交易信息以hash 和blockCount决定，根本没法索引查找，比如你想查一笔 名叫 ”xxx”的交易，对不起，不支持，不支持图片，视频，动画，音乐的存储，数据单调。讲AR存储，主要是他现在免费，所以很多人都在用，Mirror.xyz就在用，单测试发现同样问题，大的图，和视频并不在AR区块上存储，而是在Mirror这个中心化的公司的网站服务器存着，完全是旧时代产物，只能存大文本，就是字节数组，如果存...]]></description>
            <content:encoded><![CDATA[<h2 id="h-web3blockchain" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Web3是一个入口，是接入blockChain的接口，是现实中的个体进入链上世界的桥梁，是未来的趋势。</h2><p>但是现在有些突出问题，制约着链上世界的发展。</p><ul><li><p>智能合约是以状态机改变驱动的，缺少大数据存储，索引查询机制</p></li><li><p>arweave（AR）的存储基于链的开发，大的文件无法写入链上，单一全节点存储极大</p></li><li><p>智能合约设计之初较为简单，没法满足现有强大的社交、媒体、多元化信息的需求</p></li><li><p>缺少侧链接入ETH等链，融合多种信息</p></li></ul><ol><li><p>大家都知道以太坊的智能合约只是交易，即从一个地址transfer到另一个地址，引发链上状态改变，产生费用，矿机打包收费，这样的经济模式，但是问题以太坊并未对存储做出对应的设计，存储的只有交易信息，交易信息以hash 和blockCount决定，根本没法索引查找，比如你想查一笔 名叫 ”xxx”的交易，对不起，不支持，不支持图片，视频，动画，音乐的存储，数据单调。</p></li><li><p>讲AR存储，主要是他现在免费，所以很多人都在用，Mirror.xyz就在用，单测试发现同样问题，大的图，和视频并不在AR区块上存储，而是在Mirror这个中心化的公司的网站服务器存着，完全是旧时代产物，只能存大文本，就是字节数组，如果存储媒体文件，就会产生新的问题，随着区块增加，全节点的数据存储很加剧上升，导致节点会越来越少，越来越中心化，最后可能只有服务上的集群才能做节点（又回到web2），AR看了API也没索引，数据没法整理，没法归集查看，很乱。</p></li><li><p>侧链目前只专注解决ETH交易费和慢的问题，还有跨链，但是体验也不怎么好，并且把现有的ETH生态合约、数据等迁移到侧链上需要长时间的演进过程，目前缺少核心的创意。</p></li><li><p>web3的社交类等产品不纯粹，没有一个绝对web3的产品，多数还是开发商，自己搭一套web2网站，让用户以web3接入，包括聊天，发送信息等基础功能都没有实现，还是web2操作，没有一个链基于这些进行思考，扩展，行业创新能力极低，新链只是原先ETH的克隆，未对底层的交互进行设计，垃圾项目层出不穷。</p></li></ol><h3 id="h-yuan-web3" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">总结：想真正像元宇宙科幻影片一样实现 现实和链上的切换，对区块链的底层设计改动是必须的，不单纯是交易驱动状态机，还需要交互信息驱动状态机，存储驱动状态机，而这些数据，需要侧链，压缩、及优化等共同协作，这样web3 才能走进我们每一个人。</h3>]]></content:encoded>
            <author>vatalikbuterin@newsletter.paragraph.com (jambestwick)</author>
        </item>
        <item>
            <title><![CDATA[合约修饰符]]></title>
            <link>https://paragraph.com/@vatalikbuterin/548FRiw5UcO3Bg53nGWP</link>
            <guid>548FRiw5UcO3Bg53nGWP</guid>
            <pubDate>Wed, 09 Feb 2022 15:55:16 GMT</pubDate>
            <description><![CDATA[第1章: 可支付截至目前，我们只接触到很少的 函数修饰符。 要记住所有的东西很难，所以我们来个概览：我们有决定函数何时和被谁调用的可见性修饰符: private 意味着它只能被合约内部调用； internal 就像 private 但是也能被继承的合约调用； external 只能从合约外部调用；最后 public 可以在任何地方调用，不管是内部还是外部。我们也有状态修饰符， 告诉我们函数如何和区块链交互: view 告诉我们运行这个函数不会更改和保存任何数据； pure 告诉我们这个函数不但不会往区块链写数据，它甚至不从区块链读取数据。这两种在被从合约外部调用的时候都不花费任何gas（但是它们在被内部其他函数调用的时候将会耗费gas）。然后我们有了自定义的 modifiers，例如在第三课学习的: onlyOwner 和 aboveLevel。 对于这些修饰符我们可以自定义其对函数的约束逻辑。这些修饰符可以同时作用于一个函数定义上：function test() external view onlyOwner anotherModifier { /* ... */ } 在这一章...]]></description>
            <content:encoded><![CDATA[<h1 id="h-1" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">第1章: 可支付</h1><p>截至目前，我们只接触到很少的 <strong><em>函数修饰符</em></strong>。 要记住所有的东西很难，所以我们来个概览：</p><ol><li><p>我们有决定函数何时和被谁调用的可见性修饰符: <code>private</code> 意味着它只能被合约内部调用； <code>internal</code> 就像 <code>private</code> 但是也能被继承的合约调用； <code>external</code> 只能从合约外部调用；最后 <code>public</code> 可以在任何地方调用，不管是内部还是外部。</p></li><li><p>我们也有状态修饰符， 告诉我们函数如何和区块链交互: <code>view</code> 告诉我们运行这个函数不会更改和保存任何数据； <code>pure</code> 告诉我们这个函数不但不会往区块链写数据，它甚至不从区块链读取数据。这两种在被从合约外部调用的时候都不花费任何gas（但是它们在被内部其他函数调用的时候将会耗费gas）。</p></li><li><p>然后我们有了自定义的 <code>modifiers</code>，例如在第三课学习的: <code>onlyOwner</code> 和 <code>aboveLevel</code>。 对于这些修饰符我们可以自定义其对函数的约束逻辑。</p></li></ol><p>这些修饰符可以同时作用于一个函数定义上：</p><pre data-type="codeBlock" text="function test() external view onlyOwner anotherModifier { /* ... */ }
"><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">test</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title">onlyOwner</span> <span class="hljs-title">anotherModifier</span> </span>{ <span class="hljs-comment">/* ... */</span> }
</code></pre><p>在这一章，我们来学习一个新的修饰符 <code>payable</code>.</p><h2 id="h-payable" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">payable 修饰符</h2><p><code>payable</code> 方法是让 Solidity 和以太坊变得如此酷的一部分 —— 它们是一种可以接收以太的特殊函数。</p><p>先放一下。当你在调用一个普通网站服务器上的API函数的时候，你无法用你的函数传送美元——你也不能传送比特币。</p><p>但是在以太坊中， 因为钱 (<em>以太</em>), 数据 (<em>事务负载</em>)， 以及合约代码本身都存在于以太坊。你可以在同时调用函数 <strong>并</strong>付钱给另外一个合约。</p><p>这就允许出现很多有趣的逻辑， 比如向一个合约要求支付一定的钱来运行一个函数。</p><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">来看个例子</h2><pre data-type="codeBlock" text="contract OnlineStore {
  function buySomething() external payable {
    // 检查以确定0.001以太发送出去来运行函数:
    require(msg.value == 0.001 ether);
    // 如果为真，一些用来向函数调用者发送数字内容的逻辑
    transferThing(msg.sender);
  }
}
"><code><span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">OnlineStore</span> </span>{
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">buySomething</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">payable</span></span> </span>{
    <span class="hljs-comment">// 检查以确定0.001以太发送出去来运行函数:</span>
    <span class="hljs-built_in">require</span>(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">value</span> <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span><span class="hljs-number">.001</span> <span class="hljs-literal">ether</span>);
    <span class="hljs-comment">// 如果为真，一些用来向函数调用者发送数字内容的逻辑</span>
    transferThing(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>);
  }
}
</code></pre><p>在这里，<code>msg.value</code> 是一种可以查看向合约发送了多少以太的方法，另外 <code>ether</code> 是一个內建单元。</p><p>这里发生的事是，一些人会从 web3.js 调用这个函数 (从DApp的前端)， 像这样 :</p><pre data-type="codeBlock" text="// 假设 `OnlineStore` 在以太坊上指向你的合约:
OnlineStore.buySomething().send(from: web3.eth.defaultAccount, value: web3.utils.toWei(0.001))
"><code><span class="hljs-comment">// 假设 `OnlineStore` 在以太坊上指向你的合约:</span>
OnlineStore.buySomething().<span class="hljs-built_in">send</span>(<span class="hljs-keyword">from</span>: web3.eth.defaultAccount, <span class="hljs-built_in">value</span>: web3.utils.toWei(<span class="hljs-number">0</span><span class="hljs-number">.001</span>))
</code></pre><p>注意这个 <code>value</code> 字段， JavaScript 调用来指定发送多少(0.001)<code>以太</code>。如果把事务想象成一个信封，你发送到函数的参数就是信的内容。 添加一个 <code>value</code> 很像在信封里面放钱 —— 信件内容和钱同时发送给了接收者。</p><blockquote><p><em>注意： 如果一个函数没标记为</em><code>payable</code>， 而你尝试利用上面的方法发送以太，函数将拒绝你的事务。</p></blockquote>]]></content:encoded>
            <author>vatalikbuterin@newsletter.paragraph.com (jambestwick)</author>
        </item>
        <item>
            <title><![CDATA[以太坊智能合约的技巧]]></title>
            <link>https://paragraph.com/@vatalikbuterin/d2eB15C7h9PjJukP64vQ</link>
            <guid>d2eB15C7h9PjJukP64vQ</guid>
            <pubDate>Wed, 09 Feb 2022 13:57:18 GMT</pubDate>
            <description><![CDATA[非常重要的是，部署在以太坊上的 DApp，并不能保证它真正做到去中心，你需要阅读并理解它的源代码，才能防止其中没有被部署者恶意植入后门；作为开发人员，如何做到既要给自己留下修复 bug 的余地，又要尽量地放权给使用者，以便让他们放心你，从而愿意把数据放在你的 DApp 中，这确实需要个微妙的平衡。]]></description>
            <content:encoded><![CDATA[<p><em>非常重要的是，部署在以太坊上的 DApp，并不能保证它真正做到去中心，你需要阅读并理解它的源代码，才能防止其中没有被部署者恶意植入后门；作为开发人员，如何做到既要给自己留下修复 bug 的余地，又要尽量地放权给使用者，以便让他们放心你，从而愿意把数据放在你的 DApp 中，这确实需要个微妙的平衡。</em></p>]]></content:encoded>
            <author>vatalikbuterin@newsletter.paragraph.com (jambestwick)</author>
        </item>
        <item>
            <title><![CDATA[CCTV1]]></title>
            <link>https://paragraph.com/@vatalikbuterin/cctv1</link>
            <guid>Ch6ldzSbL0rWQrPxUS6I</guid>
            <pubDate>Tue, 08 Feb 2022 08:21:29 GMT</pubDate>
            <description><![CDATA[rtmp://58.200.131.2:1935/livetv/cctv1 View rtmp on Etherscan]]></description>
            <content:encoded><![CDATA[<pre data-type="codeBlock" text="rtmp://58.200.131.2:1935/livetv/cctv1
"><code>rtmp:<span class="hljs-comment">//58.200.131.2:1935/livetv/cctv1</span>
</code></pre><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><figcaption HTMLAttributes="[object Object]" class="">View rtmp on Etherscan</figcaption></figure>]]></content:encoded>
            <author>vatalikbuterin@newsletter.paragraph.com (jambestwick)</author>
        </item>
        <item>
            <title><![CDATA[FFT]]></title>
            <link>https://paragraph.com/@vatalikbuterin/fft</link>
            <guid>zWuVBfjth0c6HSQTzmbm</guid>
            <pubDate>Tue, 08 Feb 2022 08:18:27 GMT</pubDate>
            <description><![CDATA[code move]]></description>
            <content:encoded><![CDATA[<blockquote><pre data-type="codeBlock" text="code move
"><code>code move
</code></pre></blockquote>]]></content:encoded>
            <author>vatalikbuterin@newsletter.paragraph.com (jambestwick)</author>
        </item>
        <item>
            <title><![CDATA[色图网站]]></title>
            <link>https://paragraph.com/@vatalikbuterin/NdxbwMjUaUDQImFqTeKz</link>
            <guid>NdxbwMjUaUDQImFqTeKz</guid>
            <pubDate>Tue, 08 Feb 2022 08:11:38 GMT</pubDate>
            <description><![CDATA[XX网站]]></description>
            <content:encoded><![CDATA[<p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://sexycolor.vercel.app">XX网站</a></p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/cca6ce45c308b40ba0d7ad9bd420021070e91eb4be520bb247b98c6c1b9997a9.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure>]]></content:encoded>
            <author>vatalikbuterin@newsletter.paragraph.com (jambestwick)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/2ec73dcf29d443574bba4eb5bae235c393014d50ad5e3f415c2ebc8fa5dd9f8f.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[JavaMail发送邮件_jamebestwick的博客-CSDN博客]]></title>
            <link>https://paragraph.com/@vatalikbuterin/javamail-jamebestwick-csdn</link>
            <guid>aRwrB910tVDp6WVI8l1X</guid>
            <pubDate>Tue, 08 Feb 2022 06:59:04 GMT</pubDate>
            <description><![CDATA[通过指令自动化的发送邮件提示：文章写完后，目录可以自动生成，如何生成可参考右边的帮助文档文章目录通过指令自动化的发送邮件前言一、Mail（邮件）二、使用步骤1.引入库2.开启邮件服务商：POP3/SMTP服务发送QQ邮箱发送网易邮箱总结前言JAVA作为BackEnd实现邮件的定时发送，批量发送对很多业务场景有这重要的意义。例如:给用户发送发票、订阅、广告、数据的报表推送、验证账号、验证码、定时回复等等业务场景均需要该功能。因此，简单总结了下自动化发送的注意点，及实现逻辑，望大家指正。原先的文章进行更新 javaMail发送邮件正文内容一、Mail（邮件）电子邮件是—种用电子手段提供信息交换的通信方式，是互联网应用最广的服务。通过网络的电子邮件系统，用户可以以非常低廉的价格（不管发送到哪里，都只需负担网费）、非常快速的方式（几秒钟之内可以发送到世界上任何指定的目的地），与世界上任何一个角落的网络用户联系。 电子邮件可以是文字、图像、声音等多种形式。同时，用户可以得到大量免费的新闻、专题邮件，并轻松实现轻松的信息搜索。电子邮件的存在极大地方便了人与人之间的沟通与交流，促进了社会的发展...]]></description>
            <content:encoded><![CDATA[<h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">通过指令自动化的发送邮件</h2><p>提示：文章写完后，目录可以自动生成，如何生成可参考右边的帮助文档</p><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">文章目录</h3><ul><li><p>通过指令自动化的发送邮件</p></li><li><p>前言</p></li><li><p>一、Mail（邮件）</p></li><li><p>二、使用步骤</p></li><li><p>1.引入库</p><ul><li><p>2.开启邮件服务商：POP3/SMTP服务</p></li><li><p>发送QQ邮箱</p><ul><li><p>发送网易邮箱</p></li></ul></li></ul></li><li><p>总结</p></li></ul><hr><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">前言</h2><p>JAVA作为BackEnd实现邮件的定时发送，批量发送对很多业务场景有这重要的意义。例如:给用户发送发票、订阅、广告、数据的报表推送、验证账号、验证码、定时回复等等业务场景均需要该功能。因此，简单总结了下自动化发送的注意点，及实现逻辑，望大家指正。原先的文章进行更新<br><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://blog.csdn.net/baidu_30084597/article/details/104917191">javaMail发送邮件</a></p><hr><p>正文内容</p><h2 id="h-mail" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">一、Mail（邮件）</h2><p>电子邮件是—种用电子手段提供信息交换的通信方式，是互联网应用最广的服务。通过网络的电子邮件系统，用户可以以非常低廉的价格（不管发送到哪里，都只需负担网费）、非常快速的方式（几秒钟之内可以发送到世界上任何指定的目的地），与世界上任何一个角落的网络用户联系。<br>电子邮件可以是文字、图像、声音等多种形式。同时，用户可以得到大量免费的新闻、专题邮件，并轻松实现轻松的信息搜索。电子邮件的存在极大地方便了人与人之间的沟通与交流，促进了社会的发展。<br>邮件是基于<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://baike.baidu.com/item/SMTP">SMTP</a>协议的一种传输方式。<br>SMTP协议的工作过程可分为如下3个过程：</p><ol><li><p>建立连接：在这一阶段，SMTP客户请求与服务器的25端口建立一个TCP连接。一旦连接建立，SMTP服务器和客户就开始相互通告自己的域名，同时确认对方的域名。</p></li><li><p>邮件传送：利用命令，SMTP客户将邮件的源地址、目的地址和邮件的具体内容传递给SMTP服务器，SMTP服务器进行相应的响应并接收邮件。</p></li><li><p>连接释放：SMTP客户发出退出命令，服务器在处理命令后进行响应，随后关闭TCP连接。</p></li></ol><blockquote><p>邮件可以包括主题，标题、内容、附件等，附件包括音视频等各种文件类型。</p></blockquote><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/db8b04e94587133c6b91ac7168b963666d6e5f5b70542cf252adbde34b0ebb6b.png" alt="在这里插入图片描述" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">在这里插入图片描述</figcaption></figure><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">二、使用步骤</h2><h2 id="h-1" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">1.引入库</h2><p>build.gradle（示例）：</p><pre data-type="codeBlock" text="    // https://mvnrepository.com/artifact/com.sun.mail/javax.mail
    compile group: &apos;com.sun.mail&apos;, name: &apos;javax.mail&apos;, version: &apos;1.6.2&apos;
"><code>    /<span class="hljs-regexp">/ https:/</span><span class="hljs-regexp">/mvnrepository.com/artifact</span><span class="hljs-regexp">/com.sun.mail/javax</span>.mail
    compile <span class="hljs-symbol">group:</span> <span class="hljs-string">'com.sun.mail'</span>, <span class="hljs-symbol">name:</span> <span class="hljs-string">'javax.mail'</span>, <span class="hljs-symbol">version:</span> <span class="hljs-string">'1.6.2'</span>
</code></pre><p>Maven（示例）：</p><pre data-type="codeBlock" text="&lt;!-- https://mvnrepository.com/artifact/com.sun.mail/javax.mail --&gt;
&lt;dependency&gt;
    &lt;groupId&gt;com.sun.mail&lt;/groupId&gt;
    &lt;artifactId&gt;javax.mail&lt;/artifactId&gt;
    &lt;version&gt;1.6.2&lt;/version&gt;
&lt;/dependency&gt;
"><code><span class="hljs-operator">&#x3C;</span><span class="hljs-operator">!</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span> https:<span class="hljs-comment">//mvnrepository.com/artifact/com.sun.mail/javax.mail --></span>
<span class="hljs-operator">&#x3C;</span>dependency<span class="hljs-operator">></span>
    <span class="hljs-operator">&#x3C;</span>groupId<span class="hljs-operator">></span>com.sun.mail&#x3C;<span class="hljs-operator">/</span>groupId<span class="hljs-operator">></span>
    <span class="hljs-operator">&#x3C;</span>artifactId<span class="hljs-operator">></span>javax.mail&#x3C;<span class="hljs-operator">/</span>artifactId<span class="hljs-operator">></span>
    <span class="hljs-operator">&#x3C;</span>version<span class="hljs-operator">></span><span class="hljs-number">1.6</span><span class="hljs-number">.2</span><span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>version<span class="hljs-operator">></span>
<span class="hljs-operator">&#x3C;</span><span class="hljs-operator">/</span>dependency<span class="hljs-operator">></span>
</code></pre><h2 id="h-2pop3smtp" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">2.开启邮件服务商：POP3/SMTP服务</h2><p>（以QQ邮箱为示例）：</p><ol><li><p>发送QQ邮箱</p></li></ol><p>进入QQ邮箱，选择设置–&gt;账户，找到 开启服务：POP3/SMTP服务，QQ会要求你发送XX短信到指定号码，发送成功后，QQ会返回一个授权码，用于第三方登录使用，<strong>授权码一定要记住，后面程序发送邮件要用</strong>，再次登录，他就不显示了。<br><br></p><pre data-type="codeBlock" text="package com.xxx.xxx.utils;

import com.sun.mail.util.MailSSLSocketFactory;
import org.apache.commons.lang.StringUtils;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.*;
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.util.Properties;

/**
 * * Created by jambestwick1988@gmail.com
 * * github: jambestwick
 * * on 2020/3/11
 * 发送邮件工具
 * *
 */
public class SendMailAcceUtils {

    /**
     * 发送带附件的邮件
     *
     * @param receive  收件人
     * @param subject  邮件主题
     * @param msg      邮件内容
     * @param filename 附件地址，本地文件
     * @return boolean
     */
    public static boolean sendQQMail(String receive, String subject, String msg, String filename) {
        if (StringUtils.isEmpty(receive)) {
            return false;
        }
        // 发件人电子邮箱
        final String from = &quot;258702177@qq.com&quot;;
        // 发件人电子邮箱授权码
        final String pass = &quot;xxxxxxxxxuuxxxxx&quot;;

        // 指定发送邮件的主机为 smtp.qq.com
        String host = &quot;smtp.qq.com&quot;; // 邮件服务器

        // 获取系统属性
        Properties properties = System.getProperties();

        // 设置邮件服务器
        properties.setProperty(&quot;mail.smtp.host&quot;, host);
        properties.put(&quot;mail.transport.protocol&quot;, &quot;smtp&quot;);// 连接协议
        properties.put(&quot;mail.smtp.host&quot;, host);// 主机名
        properties.put(&quot;mail.smtp.port&quot;, 465);// 端口号
        properties.put(&quot;mail.smtp.auth&quot;, &quot;true&quot;);
        properties.put(&quot;mail.smtp.ssl.enable&quot;, &quot;true&quot;);// 设置是否使用ssl安全连接 ---一般都使用
        properties.put(&quot;mail.debug&quot;, &quot;true&quot;);// 设置是否显示debug信息 true 会在控制台显示相关信息
        try {
            // 得到回话对象
            Session session = Session.getInstance(properties);
            // 获取邮件对象
            Message message = new MimeMessage(session);
            // 设置发件人邮箱地址
            message.setFrom(new InternetAddress(from));
            // 设置收件人邮箱地址
            //message.setRecipients(Message.RecipientType.TO, new InternetAddress[]{new InternetAddress(receive), new InternetAddress(receive), new InternetAddress(receive)});
            message.setRecipient(Message.RecipientType.TO, new InternetAddress(receive));//一个收件人
            // 设置邮件标题
            message.setSubject(subject);
            // 创建消息部分
            BodyPart messageBodyPart = new MimeBodyPart();
            // 消息
            messageBodyPart.setText(msg);

            // 创建多重消息
            Multipart multipart = new MimeMultipart();

            // 设置文本消息部分
            multipart.addBodyPart(messageBodyPart);

            // 附件部分
            messageBodyPart = new MimeBodyPart();
            // 设置要发送附件的文件路径
            DataSource source = new FileDataSource(filename);
            messageBodyPart.setDataHandler(new DataHandler(source));

            // messageBodyPart.setFileName(filename);
            // 处理附件名称中文（附带文件路径）乱码问题
            messageBodyPart.setFileName(MimeUtility.encodeText(filename));
            multipart.addBodyPart(messageBodyPart);

            // 发送完整消息
            message.setContent(multipart);

            // 得到邮差对象
            Transport transport = session.getTransport();
            // 连接自己的邮箱账户
            transport.connect(from, pass);// 密码为QQ邮箱开通的stmp服务后得到的客户端授权码
            // 发送邮件
            transport.sendMessage(message, message.getAllRecipients());
            transport.close();
            return true;
        } catch (MessagingException | UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return false;
    }

    /***
     * 不带有附件的方法
     * 可以将发送者封装提取出来，作为入参
     * **/
    public static boolean sendQQMailWithOutFile(String receive, String subject, String msg){
        if (StringUtils.isEmpty(receive)) {
            return false;
        }
        // 发件人电子邮箱
        final String from = &quot;258702177@qq.com&quot;;
        // 发件人电子邮箱授权码
        final String pass = &quot;xxxxxxxxxxxxxxxx&quot;;

        // 指定发送邮件的主机为 smtp.qq.com
        String host = &quot;smtp.qq.com&quot;; // 邮件服务器

        // 获取系统属性
        Properties properties = System.getProperties();

        // 设置邮件服务器
        properties.setProperty(&quot;mail.smtp.host&quot;, host);
        properties.put(&quot;mail.transport.protocol&quot;, &quot;smtp&quot;);// 连接协议
        properties.put(&quot;mail.smtp.host&quot;, host);// 主机名
        properties.put(&quot;mail.smtp.port&quot;, 465);// 端口号
        properties.put(&quot;mail.smtp.auth&quot;, &quot;true&quot;);
        properties.put(&quot;mail.smtp.ssl.enable&quot;, &quot;true&quot;);// 设置是否使用ssl安全连接 ---一般都使用
        properties.put(&quot;mail.debug&quot;, &quot;true&quot;);// 设置是否显示debug信息 true 会在控制台显示相关信息
        try {
            // 得到回话对象
            Session session = Session.getInstance(properties);
            // 获取邮件对象
            Message message = new MimeMessage(session);
            // 设置发件人邮箱地址
            message.setFrom(new InternetAddress(from));
            // 设置收件人邮箱地址
            //message.setRecipients(Message.RecipientType.TO, new InternetAddress[]{new InternetAddress(receive), new InternetAddress(receive), new InternetAddress(receive)});
            message.setRecipient(Message.RecipientType.TO, new InternetAddress(receive));//一个收件人
            // 设置邮件标题
            message.setSubject(subject);
            // 创建消息部分
            BodyPart messageBodyPart = new MimeBodyPart();
            // 消息
            messageBodyPart.setText(msg);

            // 创建多重消息
            Multipart multipart = new MimeMultipart();

            // 设置文本消息部分
            multipart.addBodyPart(messageBodyPart);
            // 发送完整消息
            message.setContent(multipart);

            // 得到邮差对象
            Transport transport = session.getTransport();
            // 连接自己的邮箱账户
            transport.connect(from, pass);// 密码为QQ邮箱开通的stmp服务后得到的客户端授权码
            // 发送邮件
            transport.sendMessage(message, message.getAllRecipients());
            transport.close();
            return true;
        } catch (MessagingException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * @param send 发送者邮箱
     * @param authCode 授权码
     * @param receive 接收者邮箱
     * @param subject 邮件主题
     * @param filename 本地附件
     * **/
    public static boolean send126Mail(String send, String authCode, String receive, String subject, String msg, String filename) {
        if (StringUtils.isEmpty(receive)) {
            return false;
        }
        // 发件人电子邮箱
        PasswordAuthentication passwordAuthentication = new PasswordAuthentication(send, authCode);
        // 指定发送邮件的主机为 smtp.126.com
        String host = &quot;smtp.126.com&quot;; // 邮件服务器

        // 获取系统属性
        Properties properties = System.getProperties();
        // 1. 创建参数配置, 用于连接邮件服务器的参数配置
        properties.put(&quot;mail.transport.protocol&quot;, &quot;smtp&quot;);// 连接协议
        properties.setProperty(&quot;mail.smtp.host&quot;, host);
        //设 置 邮 件服 务 器 主 机 名
        properties.setProperty(&quot;mail.host&quot;, host);
        properties.put(&quot;mail.smtp.host&quot;, host);// 主机名
        properties.put(&quot;mail.smtp.port&quot;, 465);// 端口号
        properties.put(&quot;mail.smtp.auth&quot;, &quot;true&quot;);
        properties.put(&quot;mail.smtp.ssl.enable&quot;, &quot;true&quot;);// 设置是否使用ssl安全连接 ---一般都使用
        properties.put(&quot;mail.debug&quot;, &quot;true&quot;);// 设置是否显示debug信息 true 会在控制台显示相关信息
        try {
            //开 启 S S L 加 密，否 则 会 失 败
            MailSSLSocketFactory sf = new MailSSLSocketFactory();
            sf.setTrustAllHosts(true);
            properties.put(&quot;mail.smtp.ssl.socketFactory&quot;, sf);
            //解决附件文件名过长的问题
            properties.put(&quot;mail.mime.splitlongparameters&quot;, &quot;false&quot;);
            // 2. 根据配置创建会话对象, 用于和邮件服务器交互
            Session session = Session.getInstance(properties, new Authenticator() {
                @Override
                protected PasswordAuthentication getPasswordAuthentication() {
                    return passwordAuthentication;
                }
            });
            session.setDebug(true);                                 // 设置为debug模式, 可以查看详细的发送 log
            // 3. 创建一封邮件
            Message message = new MimeMessage(session);
            // 设置发件人邮箱地址
            message.setFrom(new InternetAddress(send));
            // 设置收件人邮箱地址
            //message.setRecipients(Message.RecipientType.TO, new InternetAddress[]{new InternetAddress(receive), new InternetAddress(receive), new InternetAddress(receive)});
            message.setRecipient(Message.RecipientType.TO, new InternetAddress(receive));//一个收件人
            // 设置邮件标题
            message.setSubject(subject);
            // 创建消息部分
            BodyPart messageBodyPart = new MimeBodyPart();
            // 消息
            messageBodyPart.setText(msg);

            // 创建多重消息
            Multipart multipart = new MimeMultipart();

            // 设置文本消息部分
            multipart.addBodyPart(messageBodyPart);

            // 附件部分
            messageBodyPart = new MimeBodyPart();
            // 设置要发送附件的文件路径
            DataSource source = new FileDataSource(filename);
            messageBodyPart.setDataHandler(new DataHandler(source));

            // messageBodyPart.setFileName(filename);
            // 处理附件名称中文（附带文件路径）乱码问题
            messageBodyPart.setFileName(MimeUtility.encodeText(filename));
            multipart.addBodyPart(messageBodyPart);

            // 发送完整消息
            message.setContent(multipart);

            // 4. 根据 Session 获取邮件传输对象
            Transport transport = session.getTransport();

            // 5. 使用 邮箱账号 和 密码 连接邮件服务器, 这里认证的邮箱必须与 message 中的发件人邮箱一致, 否则报错
            //
            //    PS_01: 成败的判断关键在此一句, 如果连接服务器失败, 都会在控制台输出相应失败原因的 log,
            //           仔细查看失败原因, 有些邮箱服务器会返回错误码或查看错误类型的链接, 根据给出的错误
            //           类型到对应邮件服务器的帮助网站上查看具体失败原因。
            //
            //    PS_02: 连接失败的原因通常为以下几点, 仔细检查代码:
            //           (1) 邮箱没有开启 SMTP 服务;
            //           (2) 邮箱密码错误, 例如某些邮箱开启了独立密码;
            //           (3) 邮箱服务器要求必须要使用 SSL 安全连接;
            //           (4) 请求过于频繁或其他原因, 被邮件服务器拒绝服务;
            //           (5) 如果以上几点都确定无误, 到邮件服务器网站查找帮助。
            //
            //    PS_03: 仔细看log, 认真看log, 看懂log, 错误原因都在log已说明。
            transport.connect(passwordAuthentication.getUserName(), passwordAuthentication.getPassword());// 密码为126邮箱开通的stmp服务后得到的客户端授权码
            // 6. 发送邮件, 发到所有的收件地址, message.getAllRecipients() 获取到的是在创建邮件对象时添加的所有收件人, 抄送人, 密送人
            transport.sendMessage(message, message.getAllRecipients());
            // 7. 关闭连接
            transport.close();
            return true;
        } catch (MessagingException | UnsupportedEncodingException | GeneralSecurityException e) {
            e.printStackTrace();
        }
        return false;
    }

}
"><code>package com.xxx.xxx.utils;

<span class="hljs-keyword">import</span> <span class="hljs-title">com</span>.<span class="hljs-title">sun</span>.<span class="hljs-title">mail</span>.<span class="hljs-title">util</span>.<span class="hljs-title">MailSSLSocketFactory</span>;
<span class="hljs-keyword">import</span> <span class="hljs-title">org</span>.<span class="hljs-title">apache</span>.<span class="hljs-title">commons</span>.<span class="hljs-title">lang</span>.<span class="hljs-title">StringUtils</span>;

<span class="hljs-keyword">import</span> <span class="hljs-title">javax</span>.<span class="hljs-title">activation</span>.<span class="hljs-title">DataHandler</span>;
<span class="hljs-keyword">import</span> <span class="hljs-title">javax</span>.<span class="hljs-title">activation</span>.<span class="hljs-title">DataSource</span>;
<span class="hljs-keyword">import</span> <span class="hljs-title">javax</span>.<span class="hljs-title">activation</span>.<span class="hljs-title">FileDataSource</span>;
<span class="hljs-keyword">import</span> <span class="hljs-title">javax</span>.<span class="hljs-title">mail</span>.<span class="hljs-operator">*</span>;
<span class="hljs-keyword">import</span> <span class="hljs-title">javax</span>.<span class="hljs-title">mail</span>.<span class="hljs-title">internet</span>.<span class="hljs-operator">*</span>;
<span class="hljs-keyword">import</span> <span class="hljs-title">java</span>.<span class="hljs-title">io</span>.<span class="hljs-title">UnsupportedEncodingException</span>;
<span class="hljs-keyword">import</span> <span class="hljs-title">java</span>.<span class="hljs-title">security</span>.<span class="hljs-title">GeneralSecurityException</span>;
<span class="hljs-keyword">import</span> <span class="hljs-title">java</span>.<span class="hljs-title">util</span>.<span class="hljs-title">Properties</span>;

<span class="hljs-comment">/**
 * * Created by jambestwick1988@gmail.com
 * * github: jambestwick
 * * on 2020/3/11
 * 发送邮件工具
 * *
 */</span>
<span class="hljs-keyword">public</span> class SendMailAcceUtils {

    <span class="hljs-comment">/**
     * 发送带附件的邮件
     *
     * @param receive  收件人
     * @param subject  邮件主题
     * @param msg      邮件内容
     * @param filename 附件地址，本地文件
     * @return boolean
     */</span>
    <span class="hljs-keyword">public</span> static boolean sendQQMail(String <span class="hljs-function"><span class="hljs-keyword">receive</span>, <span class="hljs-title">String</span> <span class="hljs-title">subject</span>, <span class="hljs-title">String</span> <span class="hljs-title"><span class="hljs-built_in">msg</span></span>, <span class="hljs-title">String</span> <span class="hljs-title">filename</span>) </span>{
        <span class="hljs-keyword">if</span> (StringUtils.isEmpty(<span class="hljs-function"><span class="hljs-keyword">receive</span>)) </span>{
            <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
        }
        <span class="hljs-comment">// 发件人电子邮箱</span>
        final String <span class="hljs-keyword">from</span> <span class="hljs-operator">=</span> <span class="hljs-string">"258702177@qq.com"</span>;
        <span class="hljs-comment">// 发件人电子邮箱授权码</span>
        final String pass <span class="hljs-operator">=</span> <span class="hljs-string">"xxxxxxxxxuuxxxxx"</span>;

        <span class="hljs-comment">// 指定发送邮件的主机为 smtp.qq.com</span>
        String host <span class="hljs-operator">=</span> <span class="hljs-string">"smtp.qq.com"</span>; <span class="hljs-comment">// 邮件服务器</span>

        <span class="hljs-comment">// 获取系统属性</span>
        Properties properties <span class="hljs-operator">=</span> System.getProperties();

        <span class="hljs-comment">// 设置邮件服务器</span>
        properties.setProperty(<span class="hljs-string">"mail.smtp.host"</span>, host);
        properties.put(<span class="hljs-string">"mail.transport.protocol"</span>, <span class="hljs-string">"smtp"</span>);<span class="hljs-comment">// 连接协议</span>
        properties.put(<span class="hljs-string">"mail.smtp.host"</span>, host);<span class="hljs-comment">// 主机名</span>
        properties.put(<span class="hljs-string">"mail.smtp.port"</span>, <span class="hljs-number">465</span>);<span class="hljs-comment">// 端口号</span>
        properties.put(<span class="hljs-string">"mail.smtp.auth"</span>, <span class="hljs-string">"true"</span>);
        properties.put(<span class="hljs-string">"mail.smtp.ssl.enable"</span>, <span class="hljs-string">"true"</span>);<span class="hljs-comment">// 设置是否使用ssl安全连接 ---一般都使用</span>
        properties.put(<span class="hljs-string">"mail.debug"</span>, <span class="hljs-string">"true"</span>);<span class="hljs-comment">// 设置是否显示debug信息 true 会在控制台显示相关信息</span>
        <span class="hljs-keyword">try</span> {
            <span class="hljs-comment">// 得到回话对象</span>
            Session session <span class="hljs-operator">=</span> Session.getInstance(properties);
            <span class="hljs-comment">// 获取邮件对象</span>
            Message message <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> MimeMessage(session);
            <span class="hljs-comment">// 设置发件人邮箱地址</span>
            message.setFrom(<span class="hljs-keyword">new</span> InternetAddress(<span class="hljs-keyword">from</span>));
            <span class="hljs-comment">// 设置收件人邮箱地址</span>
            <span class="hljs-comment">//message.setRecipients(Message.RecipientType.TO, new InternetAddress[]{new InternetAddress(receive), new InternetAddress(receive), new InternetAddress(receive)});</span>
            message.setRecipient(Message.RecipientType.TO, <span class="hljs-keyword">new</span> InternetAddress(<span class="hljs-function"><span class="hljs-keyword">receive</span>))</span>;<span class="hljs-comment">//一个收件人</span>
            <span class="hljs-comment">// 设置邮件标题</span>
            message.setSubject(subject);
            <span class="hljs-comment">// 创建消息部分</span>
            BodyPart messageBodyPart <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> MimeBodyPart();
            <span class="hljs-comment">// 消息</span>
            messageBodyPart.setText(<span class="hljs-built_in">msg</span>);

            <span class="hljs-comment">// 创建多重消息</span>
            Multipart multipart <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> MimeMultipart();

            <span class="hljs-comment">// 设置文本消息部分</span>
            multipart.addBodyPart(messageBodyPart);

            <span class="hljs-comment">// 附件部分</span>
            messageBodyPart <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> MimeBodyPart();
            <span class="hljs-comment">// 设置要发送附件的文件路径</span>
            DataSource source <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> FileDataSource(filename);
            messageBodyPart.setDataHandler(<span class="hljs-keyword">new</span> DataHandler(source));

            <span class="hljs-comment">// messageBodyPart.setFileName(filename);</span>
            <span class="hljs-comment">// 处理附件名称中文（附带文件路径）乱码问题</span>
            messageBodyPart.setFileName(MimeUtility.encodeText(filename));
            multipart.addBodyPart(messageBodyPart);

            <span class="hljs-comment">// 发送完整消息</span>
            message.setContent(multipart);

            <span class="hljs-comment">// 得到邮差对象</span>
            Transport transport <span class="hljs-operator">=</span> session.getTransport();
            <span class="hljs-comment">// 连接自己的邮箱账户</span>
            transport.connect(<span class="hljs-keyword">from</span>, pass);<span class="hljs-comment">// 密码为QQ邮箱开通的stmp服务后得到的客户端授权码</span>
            <span class="hljs-comment">// 发送邮件</span>
            transport.sendMessage(message, message.getAllRecipients());
            transport.close();
            <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
        } <span class="hljs-keyword">catch</span> (MessagingException <span class="hljs-operator">|</span> UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
    }

    <span class="hljs-comment">/***
     * 不带有附件的方法
     * 可以将发送者封装提取出来，作为入参
     * **/</span>
    <span class="hljs-keyword">public</span> static boolean sendQQMailWithOutFile(String <span class="hljs-function"><span class="hljs-keyword">receive</span>, <span class="hljs-title">String</span> <span class="hljs-title">subject</span>, <span class="hljs-title">String</span> <span class="hljs-title"><span class="hljs-built_in">msg</span></span>)</span>{
        <span class="hljs-keyword">if</span> (StringUtils.isEmpty(<span class="hljs-function"><span class="hljs-keyword">receive</span>)) </span>{
            <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
        }
        <span class="hljs-comment">// 发件人电子邮箱</span>
        final String <span class="hljs-keyword">from</span> <span class="hljs-operator">=</span> <span class="hljs-string">"258702177@qq.com"</span>;
        <span class="hljs-comment">// 发件人电子邮箱授权码</span>
        final String pass <span class="hljs-operator">=</span> <span class="hljs-string">"xxxxxxxxxxxxxxxx"</span>;

        <span class="hljs-comment">// 指定发送邮件的主机为 smtp.qq.com</span>
        String host <span class="hljs-operator">=</span> <span class="hljs-string">"smtp.qq.com"</span>; <span class="hljs-comment">// 邮件服务器</span>

        <span class="hljs-comment">// 获取系统属性</span>
        Properties properties <span class="hljs-operator">=</span> System.getProperties();

        <span class="hljs-comment">// 设置邮件服务器</span>
        properties.setProperty(<span class="hljs-string">"mail.smtp.host"</span>, host);
        properties.put(<span class="hljs-string">"mail.transport.protocol"</span>, <span class="hljs-string">"smtp"</span>);<span class="hljs-comment">// 连接协议</span>
        properties.put(<span class="hljs-string">"mail.smtp.host"</span>, host);<span class="hljs-comment">// 主机名</span>
        properties.put(<span class="hljs-string">"mail.smtp.port"</span>, <span class="hljs-number">465</span>);<span class="hljs-comment">// 端口号</span>
        properties.put(<span class="hljs-string">"mail.smtp.auth"</span>, <span class="hljs-string">"true"</span>);
        properties.put(<span class="hljs-string">"mail.smtp.ssl.enable"</span>, <span class="hljs-string">"true"</span>);<span class="hljs-comment">// 设置是否使用ssl安全连接 ---一般都使用</span>
        properties.put(<span class="hljs-string">"mail.debug"</span>, <span class="hljs-string">"true"</span>);<span class="hljs-comment">// 设置是否显示debug信息 true 会在控制台显示相关信息</span>
        <span class="hljs-keyword">try</span> {
            <span class="hljs-comment">// 得到回话对象</span>
            Session session <span class="hljs-operator">=</span> Session.getInstance(properties);
            <span class="hljs-comment">// 获取邮件对象</span>
            Message message <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> MimeMessage(session);
            <span class="hljs-comment">// 设置发件人邮箱地址</span>
            message.setFrom(<span class="hljs-keyword">new</span> InternetAddress(<span class="hljs-keyword">from</span>));
            <span class="hljs-comment">// 设置收件人邮箱地址</span>
            <span class="hljs-comment">//message.setRecipients(Message.RecipientType.TO, new InternetAddress[]{new InternetAddress(receive), new InternetAddress(receive), new InternetAddress(receive)});</span>
            message.setRecipient(Message.RecipientType.TO, <span class="hljs-keyword">new</span> InternetAddress(<span class="hljs-function"><span class="hljs-keyword">receive</span>))</span>;<span class="hljs-comment">//一个收件人</span>
            <span class="hljs-comment">// 设置邮件标题</span>
            message.setSubject(subject);
            <span class="hljs-comment">// 创建消息部分</span>
            BodyPart messageBodyPart <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> MimeBodyPart();
            <span class="hljs-comment">// 消息</span>
            messageBodyPart.setText(<span class="hljs-built_in">msg</span>);

            <span class="hljs-comment">// 创建多重消息</span>
            Multipart multipart <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> MimeMultipart();

            <span class="hljs-comment">// 设置文本消息部分</span>
            multipart.addBodyPart(messageBodyPart);
            <span class="hljs-comment">// 发送完整消息</span>
            message.setContent(multipart);

            <span class="hljs-comment">// 得到邮差对象</span>
            Transport transport <span class="hljs-operator">=</span> session.getTransport();
            <span class="hljs-comment">// 连接自己的邮箱账户</span>
            transport.connect(<span class="hljs-keyword">from</span>, pass);<span class="hljs-comment">// 密码为QQ邮箱开通的stmp服务后得到的客户端授权码</span>
            <span class="hljs-comment">// 发送邮件</span>
            transport.sendMessage(message, message.getAllRecipients());
            transport.close();
            <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
        } <span class="hljs-keyword">catch</span> (MessagingException e) {
            e.printStackTrace();
        }
        <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
    }

    <span class="hljs-comment">/**
     * @param send 发送者邮箱
     * @param authCode 授权码
     * @param receive 接收者邮箱
     * @param subject 邮件主题
     * @param filename 本地附件
     * **/</span>
    <span class="hljs-keyword">public</span> static boolean send126Mail(String send, String authCode, String <span class="hljs-function"><span class="hljs-keyword">receive</span>, <span class="hljs-title">String</span> <span class="hljs-title">subject</span>, <span class="hljs-title">String</span> <span class="hljs-title"><span class="hljs-built_in">msg</span></span>, <span class="hljs-title">String</span> <span class="hljs-title">filename</span>) </span>{
        <span class="hljs-keyword">if</span> (StringUtils.isEmpty(<span class="hljs-function"><span class="hljs-keyword">receive</span>)) </span>{
            <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
        }
        <span class="hljs-comment">// 发件人电子邮箱</span>
        PasswordAuthentication passwordAuthentication <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> PasswordAuthentication(send, authCode);
        <span class="hljs-comment">// 指定发送邮件的主机为 smtp.126.com</span>
        String host <span class="hljs-operator">=</span> <span class="hljs-string">"smtp.126.com"</span>; <span class="hljs-comment">// 邮件服务器</span>

        <span class="hljs-comment">// 获取系统属性</span>
        Properties properties <span class="hljs-operator">=</span> System.getProperties();
        <span class="hljs-comment">// 1. 创建参数配置, 用于连接邮件服务器的参数配置</span>
        properties.put(<span class="hljs-string">"mail.transport.protocol"</span>, <span class="hljs-string">"smtp"</span>);<span class="hljs-comment">// 连接协议</span>
        properties.setProperty(<span class="hljs-string">"mail.smtp.host"</span>, host);
        <span class="hljs-comment">//设 置 邮 件服 务 器 主 机 名</span>
        properties.setProperty(<span class="hljs-string">"mail.host"</span>, host);
        properties.put(<span class="hljs-string">"mail.smtp.host"</span>, host);<span class="hljs-comment">// 主机名</span>
        properties.put(<span class="hljs-string">"mail.smtp.port"</span>, <span class="hljs-number">465</span>);<span class="hljs-comment">// 端口号</span>
        properties.put(<span class="hljs-string">"mail.smtp.auth"</span>, <span class="hljs-string">"true"</span>);
        properties.put(<span class="hljs-string">"mail.smtp.ssl.enable"</span>, <span class="hljs-string">"true"</span>);<span class="hljs-comment">// 设置是否使用ssl安全连接 ---一般都使用</span>
        properties.put(<span class="hljs-string">"mail.debug"</span>, <span class="hljs-string">"true"</span>);<span class="hljs-comment">// 设置是否显示debug信息 true 会在控制台显示相关信息</span>
        <span class="hljs-keyword">try</span> {
            <span class="hljs-comment">//开 启 S S L 加 密，否 则 会 失 败</span>
            MailSSLSocketFactory sf <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> MailSSLSocketFactory();
            sf.setTrustAllHosts(<span class="hljs-literal">true</span>);
            properties.put(<span class="hljs-string">"mail.smtp.ssl.socketFactory"</span>, sf);
            <span class="hljs-comment">//解决附件文件名过长的问题</span>
            properties.put(<span class="hljs-string">"mail.mime.splitlongparameters"</span>, <span class="hljs-string">"false"</span>);
            <span class="hljs-comment">// 2. 根据配置创建会话对象, 用于和邮件服务器交互</span>
            Session session <span class="hljs-operator">=</span> Session.getInstance(properties, <span class="hljs-keyword">new</span> Authenticator() {
                @Override
                protected PasswordAuthentication getPasswordAuthentication() {
                    <span class="hljs-keyword">return</span> passwordAuthentication;
                }
            });
            session.setDebug(<span class="hljs-literal">true</span>);                                 <span class="hljs-comment">// 设置为debug模式, 可以查看详细的发送 log</span>
            <span class="hljs-comment">// 3. 创建一封邮件</span>
            Message message <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> MimeMessage(session);
            <span class="hljs-comment">// 设置发件人邮箱地址</span>
            message.setFrom(<span class="hljs-keyword">new</span> InternetAddress(send));
            <span class="hljs-comment">// 设置收件人邮箱地址</span>
            <span class="hljs-comment">//message.setRecipients(Message.RecipientType.TO, new InternetAddress[]{new InternetAddress(receive), new InternetAddress(receive), new InternetAddress(receive)});</span>
            message.setRecipient(Message.RecipientType.TO, <span class="hljs-keyword">new</span> InternetAddress(<span class="hljs-function"><span class="hljs-keyword">receive</span>))</span>;<span class="hljs-comment">//一个收件人</span>
            <span class="hljs-comment">// 设置邮件标题</span>
            message.setSubject(subject);
            <span class="hljs-comment">// 创建消息部分</span>
            BodyPart messageBodyPart <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> MimeBodyPart();
            <span class="hljs-comment">// 消息</span>
            messageBodyPart.setText(<span class="hljs-built_in">msg</span>);

            <span class="hljs-comment">// 创建多重消息</span>
            Multipart multipart <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> MimeMultipart();

            <span class="hljs-comment">// 设置文本消息部分</span>
            multipart.addBodyPart(messageBodyPart);

            <span class="hljs-comment">// 附件部分</span>
            messageBodyPart <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> MimeBodyPart();
            <span class="hljs-comment">// 设置要发送附件的文件路径</span>
            DataSource source <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> FileDataSource(filename);
            messageBodyPart.setDataHandler(<span class="hljs-keyword">new</span> DataHandler(source));

            <span class="hljs-comment">// messageBodyPart.setFileName(filename);</span>
            <span class="hljs-comment">// 处理附件名称中文（附带文件路径）乱码问题</span>
            messageBodyPart.setFileName(MimeUtility.encodeText(filename));
            multipart.addBodyPart(messageBodyPart);

            <span class="hljs-comment">// 发送完整消息</span>
            message.setContent(multipart);

            <span class="hljs-comment">// 4. 根据 Session 获取邮件传输对象</span>
            Transport transport <span class="hljs-operator">=</span> session.getTransport();

            <span class="hljs-comment">// 5. 使用 邮箱账号 和 密码 连接邮件服务器, 这里认证的邮箱必须与 message 中的发件人邮箱一致, 否则报错</span>
            <span class="hljs-comment">//</span>
            <span class="hljs-comment">//    PS_01: 成败的判断关键在此一句, 如果连接服务器失败, 都会在控制台输出相应失败原因的 log,</span>
            <span class="hljs-comment">//           仔细查看失败原因, 有些邮箱服务器会返回错误码或查看错误类型的链接, 根据给出的错误</span>
            <span class="hljs-comment">//           类型到对应邮件服务器的帮助网站上查看具体失败原因。</span>
            <span class="hljs-comment">//</span>
            <span class="hljs-comment">//    PS_02: 连接失败的原因通常为以下几点, 仔细检查代码:</span>
            <span class="hljs-comment">//           (1) 邮箱没有开启 SMTP 服务;</span>
            <span class="hljs-comment">//           (2) 邮箱密码错误, 例如某些邮箱开启了独立密码;</span>
            <span class="hljs-comment">//           (3) 邮箱服务器要求必须要使用 SSL 安全连接;</span>
            <span class="hljs-comment">//           (4) 请求过于频繁或其他原因, 被邮件服务器拒绝服务;</span>
            <span class="hljs-comment">//           (5) 如果以上几点都确定无误, 到邮件服务器网站查找帮助。</span>
            <span class="hljs-comment">//</span>
            <span class="hljs-comment">//    PS_03: 仔细看log, 认真看log, 看懂log, 错误原因都在log已说明。</span>
            transport.connect(passwordAuthentication.getUserName(), passwordAuthentication.getPassword());<span class="hljs-comment">// 密码为126邮箱开通的stmp服务后得到的客户端授权码</span>
            <span class="hljs-comment">// 6. 发送邮件, 发到所有的收件地址, message.getAllRecipients() 获取到的是在创建邮件对象时添加的所有收件人, 抄送人, 密送人</span>
            transport.sendMessage(message, message.getAllRecipients());
            <span class="hljs-comment">// 7. 关闭连接</span>
            transport.close();
            <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
        } <span class="hljs-keyword">catch</span> (MessagingException <span class="hljs-operator">|</span> UnsupportedEncodingException <span class="hljs-operator">|</span> GeneralSecurityException e) {
            e.printStackTrace();
        }
        <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
    }

}
</code></pre><ol start="2"><li><p>发送网易邮箱</p></li></ol><p>同理先进入邮箱，申请SMTP授权码，<strong>授权码一定要记住</strong> <br>测试代码：</p><pre data-type="codeBlock" text="package com.java.mail.test;

import com.java.mail.util.SendMailAcceUtils;

public class Test {
    public static void main(String[] args) {
        SendMailAcceUtils.sendQQMailWithOutFile(&quot;xxx@outlook.com&quot;,&quot;testTemp&quot;,&quot;web3j&quot;);
        SendMailAcceUtils.send126Mail(&quot;xxx@126.com&quot;,&quot;xxxx&quot;,&quot;xxx@gmail.com&quot;,&quot;web3j&quot;,&quot;wexxxx&quot;,null);
    }
}
"><code>package com.<span class="hljs-property">java</span>.<span class="hljs-property">mail</span>.<span class="hljs-property">test</span>;

<span class="hljs-keyword">import</span> com.<span class="hljs-property">java</span>.<span class="hljs-property">mail</span>.<span class="hljs-property">util</span>.<span class="hljs-property">SendMailAcceUtils</span>;

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Test</span> {
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-built_in">void</span> <span class="hljs-title function_">main</span>(<span class="hljs-params"><span class="hljs-built_in">String</span>[] args</span>) {
        <span class="hljs-title class_">SendMailAcceUtils</span>.<span class="hljs-title function_">sendQQMailWithOutFile</span>(<span class="hljs-string">"xxx@outlook.com"</span>,<span class="hljs-string">"testTemp"</span>,<span class="hljs-string">"web3j"</span>);
        <span class="hljs-title class_">SendMailAcceUtils</span>.<span class="hljs-title function_">send126Mail</span>(<span class="hljs-string">"xxx@126.com"</span>,<span class="hljs-string">"xxxx"</span>,<span class="hljs-string">"xxx@gmail.com"</span>,<span class="hljs-string">"web3j"</span>,<span class="hljs-string">"wexxxx"</span>,<span class="hljs-literal">null</span>);
    }
}
</code></pre><hr><h2 id="h-" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">总结</h2><p>提示：亲测可用。<br>项目放在github上，喜欢自取。地址:<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/ETCPark/JavaMail">https://github.com/ETCPark/JavaMail</a></p>]]></content:encoded>
            <author>vatalikbuterin@newsletter.paragraph.com (jambestwick)</author>
        </item>
        <item>
            <title><![CDATA[SushiSwap的MasterChef解读]]></title>
            <link>https://paragraph.com/@vatalikbuterin/sushiswap-masterchef</link>
            <guid>jWwdX36RGsUNX6MtZ5FN</guid>
            <pubDate>Mon, 07 Feb 2022 10:11:47 GMT</pubDate>
            <description><![CDATA[1、MasterChef的数据结构MasterChef在SushiSwap中处于核心地位，用户可以通过它进行流动性挖矿。MasterChef中包含两个主要的数据结构：UserInfo和PoolInfo 1.1、UserInfostruct UserInfo { uint256 amount; // How many LP tokens the user has provided. uint256 rewardDebt; // Reward debt. See explanation below. // // We do some fancy math here. Basically, any point in time, the amount of SUSHIs // entitled to a user but is pending to be distributed is: // // pending reward = (user.amount * pool.accSushiPerShare) - user.rewardDebt // // Whenever a user d...]]></description>
            <content:encoded><![CDATA[<h2 id="h-1masterchef" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">1、MasterChef的数据结构</h2><p>MasterChef在SushiSwap中处于核心地位，用户可以通过它进行流动性挖矿。MasterChef中包含两个主要的数据结构：UserInfo和PoolInfo</p><p>1.1、UserInfo</p><pre data-type="codeBlock" text="struct UserInfo {
        uint256 amount; // How many LP tokens the user has provided.
        uint256 rewardDebt; // Reward debt. See explanation below.
        //
        // We do some fancy math here. Basically, any point in time, the amount of SUSHIs
        // entitled to a user but is pending to be distributed is:
        //
        //   pending reward = (user.amount * pool.accSushiPerShare) - user.rewardDebt
        //
        // Whenever a user deposits or withdraws LP tokens to a pool. Here&apos;s what happens:
        //   1. The pool&apos;s `accSushiPerShare` (and `lastRewardBlock`) gets updated.
        //   2. User receives the pending reward sent to his/her address.
        //   3. User&apos;s `amount` gets updated.
        //   4. User&apos;s `rewardDebt` gets updated.
    }
"><code><span class="hljs-keyword">struct</span> <span class="hljs-title">UserInfo</span> {
        <span class="hljs-keyword">uint256</span> amount; <span class="hljs-comment">// How many LP tokens the user has provided.</span>
        <span class="hljs-keyword">uint256</span> rewardDebt; <span class="hljs-comment">// Reward debt. See explanation below.</span>
        <span class="hljs-comment">//</span>
        <span class="hljs-comment">// We do some fancy math here. Basically, any point in time, the amount of SUSHIs</span>
        <span class="hljs-comment">// entitled to a user but is pending to be distributed is:</span>
        <span class="hljs-comment">//</span>
        <span class="hljs-comment">//   pending reward = (user.amount * pool.accSushiPerShare) - user.rewardDebt</span>
        <span class="hljs-comment">//</span>
        <span class="hljs-comment">// Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens:</span>
        <span class="hljs-comment">//   1. The pool's `accSushiPerShare` (and `lastRewardBlock`) gets updated.</span>
        <span class="hljs-comment">//   2. User receives the pending reward sent to his/her address.</span>
        <span class="hljs-comment">//   3. User's `amount` gets updated.</span>
        <span class="hljs-comment">//   4. User's `rewardDebt` gets updated.</span>
    }
</code></pre><p>amount是用户质押的LPToken数量，rewardDebt代表用户已经获取的奖励数。</p><p>1.2、PoolInfo</p><pre data-type="codeBlock" text="struct PoolInfo {
        IERC20 lpToken; // Address of LP token contract.
        uint256 allocPoint; // How many allocation points assigned to this pool. SUSHIs to distribute per block.
        uint256 lastRewardBlock; // Last block number that SUSHIs distribution occurs.
        uint256 accSushiPerShare; // Accumulated SUSHIs per share, times 1e12. See below.
    }
"><code><span class="hljs-keyword">struct</span> <span class="hljs-title">PoolInfo</span> {
        IERC20 lpToken; <span class="hljs-comment">// Address of LP token contract.</span>
        <span class="hljs-keyword">uint256</span> allocPoint; <span class="hljs-comment">// How many allocation points assigned to this pool. SUSHIs to distribute per block.</span>
        <span class="hljs-keyword">uint256</span> lastRewardBlock; <span class="hljs-comment">// Last block number that SUSHIs distribution occurs.</span>
        <span class="hljs-keyword">uint256</span> accSushiPerShare; <span class="hljs-comment">// Accumulated SUSHIs per share, times 1e12. See below.</span>
    }
</code></pre><p>lpToken是ERC20标准代币，SushiSwap最初的LPToken是Uniswap的流动性，Uniswap质押后生成的流动性其实是UniswapPair的代币，SushiSwap将UniswapPair的地址设置到pool里，就可以将Uniswap的流动性进行质押操作。后来SushiSwap完成了一次迁移，LPToken就从Uniswap的流动性代币变成了SushiSwap的流动性代币。</p><p>allocPoint是质押池的分配比例，lastRewardBlock是上一次分配奖励的区块数。</p><p>accSushiPerShare是质押一个LPToken的全局收益，用户依赖这个计算实际收益，原理很简单，用户在质押LPToken的时候，会把当前accSushiPerShare记下来作为起始点位，当解除质押的时候，可以通过最新的accSushiPerShare减去起始点位，就可以得到用户实际的收益。</p><p>1.3、其他数据结构</p><pre data-type="codeBlock" text="    SushiToken public sushi;
    // Dev address.
    address public devaddr;
    // Block number when bonus SUSHI period ends.
    uint256 public bonusEndBlock;
    // SUSHI tokens created per block.
    uint256 public sushiPerBlock;
    // Bonus muliplier for early sushi makers.
    uint256 public constant BONUS_MULTIPLIER = 10;
    // The migrator contract. It has a lot of power. Can only be set through governance (owner).
    IMigratorChef public migrator;
    // Info of each pool.
    PoolInfo[] public poolInfo;
    // Info of each user that stakes LP tokens.
    mapping(uint256 =&gt; mapping(address =&gt; UserInfo)) public userInfo;
    // Total allocation poitns. Must be the sum of all allocation points in all pools.
    uint256 public totalAllocPoint = 0;
    // The block number when SUSHI mining starts.
    uint256 public startBlock;
"><code>    SushiToken <span class="hljs-keyword">public</span> sushi;
    <span class="hljs-comment">// Dev address.</span>
    <span class="hljs-keyword">address</span> <span class="hljs-keyword">public</span> devaddr;
    <span class="hljs-comment">// Block number when bonus SUSHI period ends.</span>
    <span class="hljs-keyword">uint256</span> <span class="hljs-keyword">public</span> bonusEndBlock;
    <span class="hljs-comment">// SUSHI tokens created per block.</span>
    <span class="hljs-keyword">uint256</span> <span class="hljs-keyword">public</span> sushiPerBlock;
    <span class="hljs-comment">// Bonus muliplier for early sushi makers.</span>
    <span class="hljs-keyword">uint256</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">constant</span> BONUS_MULTIPLIER <span class="hljs-operator">=</span> <span class="hljs-number">10</span>;
    <span class="hljs-comment">// The migrator contract. It has a lot of power. Can only be set through governance (owner).</span>
    IMigratorChef <span class="hljs-keyword">public</span> migrator;
    <span class="hljs-comment">// Info of each pool.</span>
    PoolInfo[] <span class="hljs-keyword">public</span> poolInfo;
    <span class="hljs-comment">// Info of each user that stakes LP tokens.</span>
    <span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">uint256</span> <span class="hljs-operator">=</span><span class="hljs-operator">></span> <span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">address</span> <span class="hljs-operator">=</span><span class="hljs-operator">></span> UserInfo)) <span class="hljs-keyword">public</span> userInfo;
    <span class="hljs-comment">// Total allocation poitns. Must be the sum of all allocation points in all pools.</span>
    <span class="hljs-keyword">uint256</span> <span class="hljs-keyword">public</span> totalAllocPoint <span class="hljs-operator">=</span> <span class="hljs-number">0</span>;
    <span class="hljs-comment">// The block number when SUSHI mining starts.</span>
    <span class="hljs-keyword">uint256</span> <span class="hljs-keyword">public</span> startBlock;
</code></pre><p>sushi是一个ERC20代币，质押流动性获取的就是这种代币奖励。</p><p>devaddr是开发者地址，用于分配sushi奖励的手续费</p><p>bonusEndBlock，刚开始sushi是借Uniswap的流动性进行质押的，为了吸引用户，设置了一个奖励值乘数BONUS_MULTIPLIER和一个奖励截止区块bonusEndBlock，在bonusEndBlock前的奖励获得数量都会乘以10，这个区块后会执行迁移，迁移后就没有了加倍奖励，后续这个值也用不到了。</p><p>sushiPerBlock，每个区块挖出来的sushi的数量</p><p>migrator，迁移工具类，实现原理就是根据UniswapPair创建一个一模一样的SushiSwapPair，然后用用户的UniswapPair流动性赎回交易对（比如USDT/DAI），然后将交易对在SushiSwapPair中添加，获取SushiSwapPair的流动性代币，最后将SushiSwapPair的流动性代币进行质押。</p><p>totalAllocPoint是总共分配的点数</p><p>startBlock是开始区块</p><h2 id="h-2" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">2、构造函数</h2><pre data-type="codeBlock" text="constructor(
        SushiToken _sushi,
        address _devaddr,
        uint256 _sushiPerBlock,
        uint256 _startBlock,
        uint256 _bonusEndBlock
    ) public {
        sushi = _sushi;
        devaddr = _devaddr;
        sushiPerBlock = _sushiPerBlock;
        bonusEndBlock = _bonusEndBlock;
        startBlock = _startBlock;
    }
"><code>constructor(
        SushiToken _sushi,
        address _devaddr,
        uint256 _sushiPerBlock,
        uint256 _startBlock,
        uint256 _bonusEndBlock
    ) public {
        <span class="hljs-attr">sushi</span> = _sushi<span class="hljs-comment">;</span>
        <span class="hljs-attr">devaddr</span> = _devaddr<span class="hljs-comment">;</span>
        <span class="hljs-attr">sushiPerBlock</span> = _sushiPerBlock<span class="hljs-comment">;</span>
        <span class="hljs-attr">bonusEndBlock</span> = _bonusEndBlock<span class="hljs-comment">;</span>
        <span class="hljs-attr">startBlock</span> = _startBlock<span class="hljs-comment">;</span>
    }
</code></pre><p>MasterChef初始化传入sushi代币的地址（值为<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://etherscan.io/address/0x6b3595068778dd592e39a122f4f5a5cf09c90fe2">0x6b3595068778dd592e39a122f4f5a5cf09c90fe2</a>），开发者地址（值为<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://etherscan.io/address/0xe94b5eec1fa96ceecbd33ef5baa8d00e4493f4f3">0xe94b5eec1fa96ceecbd33ef5baa8d00e4493f4f3</a> ），每个块分配sushi的数量（值为<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://etherscan.io/unitconverter?wei=100000000000000000000">100</a>*1e18），奖励结束区块(值为10850000)以及开始区块（值为10750000）</p><h2 id="h-3" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">3、添加质押池</h2><pre data-type="codeBlock" text="function add(
        uint256 _allocPoint,
        IERC20 _lpToken,
        bool _withUpdate
    ) public onlyOwner {
        if (_withUpdate) {
            massUpdatePools();
        }
        uint256 lastRewardBlock =
            block.number &gt; startBlock ? block.number : startBlock;
        totalAllocPoint = totalAllocPoint.add(_allocPoint);
        poolInfo.push(
            PoolInfo({
                lpToken: _lpToken,
                allocPoint: _allocPoint,
                lastRewardBlock: lastRewardBlock,
                accSushiPerShare: 0
            })
        );
    }
"><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">add</span>(<span class="hljs-params">
        <span class="hljs-keyword">uint256</span> _allocPoint,
        IERC20 _lpToken,
        <span class="hljs-keyword">bool</span> _withUpdate
    </span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title">onlyOwner</span> </span>{
        <span class="hljs-keyword">if</span> (_withUpdate) {
            massUpdatePools();
        }
        <span class="hljs-keyword">uint256</span> lastRewardBlock <span class="hljs-operator">=</span>
            <span class="hljs-built_in">block</span>.<span class="hljs-built_in">number</span> <span class="hljs-operator">></span> startBlock ? <span class="hljs-built_in">block</span>.<span class="hljs-built_in">number</span> : startBlock;
        totalAllocPoint <span class="hljs-operator">=</span> totalAllocPoint.add(_allocPoint);
        poolInfo.<span class="hljs-built_in">push</span>(
            PoolInfo({
                lpToken: _lpToken,
                allocPoint: _allocPoint,
                lastRewardBlock: lastRewardBlock,
                accSushiPerShare: <span class="hljs-number">0</span>
            })
        );
    }
</code></pre><p>代码很简单，生成一个poolInfo然后加入数组中，然后更新totalAllocPoint，其中_allocPoint是指这个池质押挖矿的比例。比如totalAllocPoint是10000，_allocPoint是100，每个区块一共挖100个，那么每个区块这个池分配到的就是100*（100/10000） = 1</p><p>本方法只有管理员可以执行，因为有onlyOwner这个modifier</p><h2 id="h-4" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">4、修改质押池参数</h2><pre data-type="codeBlock" text="function set(
        uint256 _pid,
        uint256 _allocPoint,
        bool _withUpdate
    ) public onlyOwner {
        if (_withUpdate) {
            massUpdatePools();
        }
        totalAllocPoint = totalAllocPoint.sub(poolInfo[_pid].allocPoint).add(
            _allocPoint
        );
        poolInfo[_pid].allocPoint = _allocPoint;
    }
"><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">set</span>(<span class="hljs-params">
        <span class="hljs-keyword">uint256</span> _pid,
        <span class="hljs-keyword">uint256</span> _allocPoint,
        <span class="hljs-keyword">bool</span> _withUpdate
    </span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title">onlyOwner</span> </span>{
        <span class="hljs-keyword">if</span> (_withUpdate) {
            massUpdatePools();
        }
        totalAllocPoint <span class="hljs-operator">=</span> totalAllocPoint.sub(poolInfo[_pid].allocPoint).add(
            _allocPoint
        );
        poolInfo[_pid].allocPoint <span class="hljs-operator">=</span> _allocPoint;
    }
</code></pre><p>目前来看只能修改质押挖矿的分配比例，也是只有管理员可以执行。</p><h2 id="h-5" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">5、执行迁移</h2><pre data-type="codeBlock" text="function setMigrator(IMigratorChef _migrator) public onlyOwner {
        migrator = _migrator;
    }


function migrate(uint256 _pid) public {
        require(address(migrator) != address(0), &quot;migrate: no migrator&quot;);
        PoolInfo storage pool = poolInfo[_pid];
        IERC20 lpToken = pool.lpToken;
        uint256 bal = lpToken.balanceOf(address(this));
        lpToken.safeApprove(address(migrator), bal);
        IERC20 newLpToken = migrator.migrate(lpToken);
        require(bal == newLpToken.balanceOf(address(this)), &quot;migrate: bad&quot;);
        pool.lpToken = newLpToken;
    }
"><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">setMigrator</span>(<span class="hljs-params">IMigratorChef _migrator</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title">onlyOwner</span> </span>{
        migrator <span class="hljs-operator">=</span> _migrator;
    }


<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">migrate</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> _pid</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        <span class="hljs-built_in">require</span>(<span class="hljs-keyword">address</span>(migrator) <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>), <span class="hljs-string">"migrate: no migrator"</span>);
        PoolInfo <span class="hljs-keyword">storage</span> pool <span class="hljs-operator">=</span> poolInfo[_pid];
        IERC20 lpToken <span class="hljs-operator">=</span> pool.lpToken;
        <span class="hljs-keyword">uint256</span> bal <span class="hljs-operator">=</span> lpToken.balanceOf(<span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>));
        lpToken.safeApprove(<span class="hljs-keyword">address</span>(migrator), bal);
        IERC20 newLpToken <span class="hljs-operator">=</span> migrator.migrate(lpToken);
        <span class="hljs-built_in">require</span>(bal <span class="hljs-operator">=</span><span class="hljs-operator">=</span> newLpToken.balanceOf(<span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>)), <span class="hljs-string">"migrate: bad"</span>);
        pool.lpToken <span class="hljs-operator">=</span> newLpToken;
    }
</code></pre><p>管理员会先设置迁移器，然后针对单个质押池进行迁移。迁移流程先对迁移器进行授权（safeApprove），后面执行由migrator控制，migrator会返回一个新的LPToken，然后重置质押池。下面看看sushi的migrator是怎么操作的：</p><pre data-type="codeBlock" text="function migrate(IUniswapV2Pair orig) public returns (IUniswapV2Pair) {
        require(msg.sender == chef, &quot;not from master chef&quot;);
        require(block.number &gt;= notBeforeBlock, &quot;too early to migrate&quot;);
        require(orig.factory() == oldFactory, &quot;not from old factory&quot;);
        address token0 = orig.token0();
        address token1 = orig.token1();
        IUniswapV2Pair pair = IUniswapV2Pair(factory.getPair(token0, token1));
        if (pair == IUniswapV2Pair(address(0))) {
            pair = IUniswapV2Pair(factory.createPair(token0, token1));
        }
        uint256 lp = orig.balanceOf(msg.sender);
        if (lp == 0) return pair;
        desiredLiquidity = lp;
        //用户的流动性还给Uniswap
        orig.transferFrom(msg.sender, address(orig), lp);
        //Uniswap把质押的代币交易对给到sushiswap的pair
        orig.burn(address(pair));
        //sushiswap给用户发放流动性
        pair.mint(msg.sender);
        desiredLiquidity = uint256(-1);
        return pair;
    }
"><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">migrate</span>(<span class="hljs-params">IUniswapV2Pair orig</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params">IUniswapV2Pair</span>) </span>{
        <span class="hljs-built_in">require</span>(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span> <span class="hljs-operator">=</span><span class="hljs-operator">=</span> chef, <span class="hljs-string">"not from master chef"</span>);
        <span class="hljs-built_in">require</span>(<span class="hljs-built_in">block</span>.<span class="hljs-built_in">number</span> <span class="hljs-operator">></span><span class="hljs-operator">=</span> notBeforeBlock, <span class="hljs-string">"too early to migrate"</span>);
        <span class="hljs-built_in">require</span>(orig.factory() <span class="hljs-operator">=</span><span class="hljs-operator">=</span> oldFactory, <span class="hljs-string">"not from old factory"</span>);
        <span class="hljs-keyword">address</span> token0 <span class="hljs-operator">=</span> orig.token0();
        <span class="hljs-keyword">address</span> token1 <span class="hljs-operator">=</span> orig.token1();
        IUniswapV2Pair pair <span class="hljs-operator">=</span> IUniswapV2Pair(factory.getPair(token0, token1));
        <span class="hljs-keyword">if</span> (pair <span class="hljs-operator">=</span><span class="hljs-operator">=</span> IUniswapV2Pair(<span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>))) {
            pair <span class="hljs-operator">=</span> IUniswapV2Pair(factory.createPair(token0, token1));
        }
        <span class="hljs-keyword">uint256</span> lp <span class="hljs-operator">=</span> orig.balanceOf(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>);
        <span class="hljs-keyword">if</span> (lp <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span> pair;
        desiredLiquidity <span class="hljs-operator">=</span> lp;
        <span class="hljs-comment">//用户的流动性还给Uniswap</span>
        orig.transferFrom(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>, <span class="hljs-keyword">address</span>(orig), lp);
        <span class="hljs-comment">//Uniswap把质押的代币交易对给到sushiswap的pair</span>
        orig.burn(<span class="hljs-keyword">address</span>(pair));
        <span class="hljs-comment">//sushiswap给用户发放流动性</span>
        pair.mint(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>);
        desiredLiquidity <span class="hljs-operator">=</span> <span class="hljs-keyword">uint256</span>(<span class="hljs-number">-1</span>);
        <span class="hljs-keyword">return</span> pair;
    }
</code></pre><p>正如上文所述，sushiswap一开始借助的是uniswap的流动性，因此上面的lpToken传过来的其实是UniswapPair，然后通过UniswapPair拿到具体的交易对里的两个token，然后在sushi中创建SushiSwapPair（都是IUniswapV2Pair接口的实现类），然后将用户在Uniswap的流动性赎回(先转给Uniswap，然后调用burn，注意这里burn的对象是pair，这样Uniswap会把两个质押token还到SushiSwapPair的地址)，最后调用SushiSwapPair的mint给用户增发SushiSwapPair的流动性，从而完成用户流动性的迁移。</p><h2 id="h-6" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">6、更新质押池收益</h2><pre data-type="codeBlock" text="function updatePool(uint256 _pid) public {
        PoolInfo storage pool = poolInfo[_pid];
        if (block.number &lt;= pool.lastRewardBlock) {
            return;
        }
        uint256 lpSupply = pool.lpToken.balanceOf(address(this));
        if (lpSupply == 0) {
            pool.lastRewardBlock = block.number;
            return;
        }
        uint256 multiplier = getMultiplier(pool.lastRewardBlock, block.number);
        uint256 sushiReward =
            multiplier.mul(sushiPerBlock).mul(pool.allocPoint).div(
                totalAllocPoint
            );
        sushi.mint(devaddr, sushiReward.div(10));
        sushi.mint(address(this), sushiReward);
        pool.accSushiPerShare = pool.accSushiPerShare.add(
            sushiReward.mul(1e12).div(lpSupply)
        );
        pool.lastRewardBlock = block.number;
    }
"><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">updatePool</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> _pid</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        PoolInfo <span class="hljs-keyword">storage</span> pool <span class="hljs-operator">=</span> poolInfo[_pid];
        <span class="hljs-keyword">if</span> (<span class="hljs-built_in">block</span>.<span class="hljs-built_in">number</span> <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">=</span> pool.lastRewardBlock) {
            <span class="hljs-keyword">return</span>;
        }
        <span class="hljs-keyword">uint256</span> lpSupply <span class="hljs-operator">=</span> pool.lpToken.balanceOf(<span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>));
        <span class="hljs-keyword">if</span> (lpSupply <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span>) {
            pool.lastRewardBlock <span class="hljs-operator">=</span> <span class="hljs-built_in">block</span>.<span class="hljs-built_in">number</span>;
            <span class="hljs-keyword">return</span>;
        }
        <span class="hljs-keyword">uint256</span> multiplier <span class="hljs-operator">=</span> getMultiplier(pool.lastRewardBlock, <span class="hljs-built_in">block</span>.<span class="hljs-built_in">number</span>);
        <span class="hljs-keyword">uint256</span> sushiReward <span class="hljs-operator">=</span>
            multiplier.mul(sushiPerBlock).mul(pool.allocPoint).div(
                totalAllocPoint
            );
        sushi.mint(devaddr, sushiReward.div(<span class="hljs-number">10</span>));
        sushi.mint(<span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>), sushiReward);
        pool.accSushiPerShare <span class="hljs-operator">=</span> pool.accSushiPerShare.add(
            sushiReward.mul(<span class="hljs-number">1e12</span>).div(lpSupply)
        );
        pool.lastRewardBlock <span class="hljs-operator">=</span> <span class="hljs-built_in">block</span>.<span class="hljs-built_in">number</span>;
    }
</code></pre><p>首先会计算质押池lpToken的数量，如果为0，就只更新lastRewardBlock。否则会先计算一个乘数multiplier</p><pre data-type="codeBlock" text="// Return reward multiplier over the given _from to _to block.
    function getMultiplier(uint256 _from, uint256 _to)
        public
        view
        returns (uint256)
    {
        if (_to &lt;= bonusEndBlock) {
            return _to.sub(_from).mul(BONUS_MULTIPLIER);
        } else if (_from &gt;= bonusEndBlock) {
            return _to.sub(_from);
        } else {
            return
                bonusEndBlock.sub(_from).mul(BONUS_MULTIPLIER).add(
                    _to.sub(bonusEndBlock)
                );
        }
    }
"><code><span class="hljs-comment">// Return reward multiplier over the given _from to _to block.</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getMultiplier</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> _from, <span class="hljs-keyword">uint256</span> _to</span>)
        <span class="hljs-title"><span class="hljs-keyword">public</span></span>
        <span class="hljs-title"><span class="hljs-keyword">view</span></span>
        <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint256</span></span>)
    </span>{
        <span class="hljs-keyword">if</span> (_to <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">=</span> bonusEndBlock) {
            <span class="hljs-keyword">return</span> _to.sub(_from).mul(BONUS_MULTIPLIER);
        } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (_from <span class="hljs-operator">></span><span class="hljs-operator">=</span> bonusEndBlock) {
            <span class="hljs-keyword">return</span> _to.sub(_from);
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-keyword">return</span>
                bonusEndBlock.sub(_from).mul(BONUS_MULTIPLIER).add(
                    _to.sub(bonusEndBlock)
                );
        }
    }
</code></pre><p>这里的计算是为了兼容bonusEndBlock，如果是to小于bonusEndBlock，说明质押池完全处于奖励挖矿阶段，会乘以一个倍数BONUS_MULTIPLIER，如果from大于bonusEndBlock，说明质押池完全没参与奖励挖矿，所以简单的to-from就可以了。最后一个else是处理质押池部分参与奖励挖矿，部分是结束后的常规挖矿。</p><p>multiplier的计算是从lastRewardBlock到当前区块的奖励区块数，获取multiplier后开始计算这一段时间的sushiReward</p><pre data-type="codeBlock" text="uint256 sushiReward =
            multiplier.mul(sushiPerBlock).mul(pool.allocPoint).div(
                totalAllocPoint
            );
"><code><span class="hljs-keyword">uint256</span> sushiReward <span class="hljs-operator">=</span>
            multiplier.mul(sushiPerBlock).mul(pool.allocPoint).div(
                totalAllocPoint
            );
</code></pre><p>multiplier*sushiPerBlock是总的sushi奖励，pool.allocPoint/totalAllocPoint是当前质押池的分配比例。</p><p>接下来给开发者地址分配10%的sushiReward作为手续费，然后总的sushiReward分配给当前质押池。</p><p>然后计算一下accSushiPerShare进行累加。</p><p>最后更新lastRewardBlock。</p><h2 id="h-7" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">7、查看用户质押收益</h2><pre data-type="codeBlock" text="function pendingSushi(uint256 _pid, address _user)
        external
        view
        returns (uint256)
    {
        PoolInfo storage pool = poolInfo[_pid];
        UserInfo storage user = userInfo[_pid][_user];
        uint256 accSushiPerShare = pool.accSushiPerShare;
        uint256 lpSupply = pool.lpToken.balanceOf(address(this));
        if (block.number &gt; pool.lastRewardBlock &amp;&amp; lpSupply != 0) {
            uint256 multiplier =
                getMultiplier(pool.lastRewardBlock, block.number);
            uint256 sushiReward =
                multiplier.mul(sushiPerBlock).mul(pool.allocPoint).div(
                    totalAllocPoint
                );
            accSushiPerShare = accSushiPerShare.add(
                sushiReward.mul(1e12).div(lpSupply)
            );
        }
        return user.amount.mul(accSushiPerShare).div(1e12).sub(user.rewardDebt);
    }
"><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">pendingSushi</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> _pid, <span class="hljs-keyword">address</span> _user</span>)
        <span class="hljs-title"><span class="hljs-keyword">external</span></span>
        <span class="hljs-title"><span class="hljs-keyword">view</span></span>
        <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint256</span></span>)
    </span>{
        PoolInfo <span class="hljs-keyword">storage</span> pool <span class="hljs-operator">=</span> poolInfo[_pid];
        UserInfo <span class="hljs-keyword">storage</span> user <span class="hljs-operator">=</span> userInfo[_pid][_user];
        <span class="hljs-keyword">uint256</span> accSushiPerShare <span class="hljs-operator">=</span> pool.accSushiPerShare;
        <span class="hljs-keyword">uint256</span> lpSupply <span class="hljs-operator">=</span> pool.lpToken.balanceOf(<span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>));
        <span class="hljs-keyword">if</span> (<span class="hljs-built_in">block</span>.<span class="hljs-built_in">number</span> <span class="hljs-operator">></span> pool.lastRewardBlock <span class="hljs-operator">&#x26;</span><span class="hljs-operator">&#x26;</span> lpSupply <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span>) {
            <span class="hljs-keyword">uint256</span> multiplier <span class="hljs-operator">=</span>
                getMultiplier(pool.lastRewardBlock, <span class="hljs-built_in">block</span>.<span class="hljs-built_in">number</span>);
            <span class="hljs-keyword">uint256</span> sushiReward <span class="hljs-operator">=</span>
                multiplier.mul(sushiPerBlock).mul(pool.allocPoint).div(
                    totalAllocPoint
                );
            accSushiPerShare <span class="hljs-operator">=</span> accSushiPerShare.add(
                sushiReward.mul(<span class="hljs-number">1e12</span>).div(lpSupply)
            );
        }
        <span class="hljs-keyword">return</span> user.amount.mul(accSushiPerShare).div(<span class="hljs-number">1e12</span>).sub(user.rewardDebt);
    }
</code></pre><p>前面所有的逻辑都在更新当前质押池的最新收益，逻辑和updatePool类似，但是不执行mint，仅仅是逻辑上计算。最后一行通过通过用户质押的ammount乘以accSushiPerShare，得到理论上用户一共获得的sushi数量，然后减去用户实际已经获得的sushi数量rewardDebt，就是剩余还未获得的数据。</p><h2 id="h-8lptoken" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">8、用户质押LPToken进行挖矿</h2><pre data-type="codeBlock" text="function deposit(uint256 _pid, uint256 _amount) public {
        PoolInfo storage pool = poolInfo[_pid];
        UserInfo storage user = userInfo[_pid][msg.sender];
        updatePool(_pid);
        if (user.amount &gt; 0) {
            uint256 pending =
                user.amount.mul(pool.accSushiPerShare).div(1e12).sub(
                    user.rewardDebt
                );
            safeSushiTransfer(msg.sender, pending);
        }
        pool.lpToken.safeTransferFrom(
            address(msg.sender),
            address(this),
            _amount
        );
        user.amount = user.amount.add(_amount);
        user.rewardDebt = user.amount.mul(pool.accSushiPerShare).div(1e12);
        emit Deposit(msg.sender, _pid, _amount);
    }
"><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">deposit</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> _pid, <span class="hljs-keyword">uint256</span> _amount</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        PoolInfo <span class="hljs-keyword">storage</span> pool <span class="hljs-operator">=</span> poolInfo[_pid];
        UserInfo <span class="hljs-keyword">storage</span> user <span class="hljs-operator">=</span> userInfo[_pid][<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>];
        updatePool(_pid);
        <span class="hljs-keyword">if</span> (user.amount <span class="hljs-operator">></span> <span class="hljs-number">0</span>) {
            <span class="hljs-keyword">uint256</span> pending <span class="hljs-operator">=</span>
                user.amount.mul(pool.accSushiPerShare).div(<span class="hljs-number">1e12</span>).sub(
                    user.rewardDebt
                );
            safeSushiTransfer(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>, pending);
        }
        pool.lpToken.safeTransferFrom(
            <span class="hljs-keyword">address</span>(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>),
            <span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>),
            _amount
        );
        user.amount <span class="hljs-operator">=</span> user.amount.add(_amount);
        user.rewardDebt <span class="hljs-operator">=</span> user.amount.mul(pool.accSushiPerShare).div(<span class="hljs-number">1e12</span>);
        <span class="hljs-keyword">emit</span> Deposit(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>, _pid, _amount);
    }
</code></pre><p>先更新了质押池收益，然后计算用户未获得的sushi收益（如果用户之前已经质押了），将这些收益转到用户账户。然后将用户的LPToken转移给质押池，最后更新用户质押的LPToken数量，将最新的amount*accSushiPerShare设置为rewardDebt，这一步操作其实就是设置了一个用户奖励的起始点位，而上面的pendingSushi的计算恰恰依赖这个起始点位。</p><h2 id="h-9" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">9、解除质押</h2><pre data-type="codeBlock" text="function withdraw(uint256 _pid, uint256 _amount) public {
        PoolInfo storage pool = poolInfo[_pid];
        UserInfo storage user = userInfo[_pid][msg.sender];
        require(user.amount &gt;= _amount, &quot;withdraw: not good&quot;);
        updatePool(_pid);
        uint256 pending =
            user.amount.mul(pool.accSushiPerShare).div(1e12).sub(
                user.rewardDebt
            );
        safeSushiTransfer(msg.sender, pending);
        user.amount = user.amount.sub(_amount);
        user.rewardDebt = user.amount.mul(pool.accSushiPerShare).div(1e12);
        pool.lpToken.safeTransfer(address(msg.sender), _amount);
        emit Withdraw(msg.sender, _pid, _amount);
    }
"><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">withdraw</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> _pid, <span class="hljs-keyword">uint256</span> _amount</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        PoolInfo <span class="hljs-keyword">storage</span> pool <span class="hljs-operator">=</span> poolInfo[_pid];
        UserInfo <span class="hljs-keyword">storage</span> user <span class="hljs-operator">=</span> userInfo[_pid][<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>];
        <span class="hljs-built_in">require</span>(user.amount <span class="hljs-operator">></span><span class="hljs-operator">=</span> _amount, <span class="hljs-string">"withdraw: not good"</span>);
        updatePool(_pid);
        <span class="hljs-keyword">uint256</span> pending <span class="hljs-operator">=</span>
            user.amount.mul(pool.accSushiPerShare).div(<span class="hljs-number">1e12</span>).sub(
                user.rewardDebt
            );
        safeSushiTransfer(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>, pending);
        user.amount <span class="hljs-operator">=</span> user.amount.sub(_amount);
        user.rewardDebt <span class="hljs-operator">=</span> user.amount.mul(pool.accSushiPerShare).div(<span class="hljs-number">1e12</span>);
        pool.lpToken.safeTransfer(<span class="hljs-keyword">address</span>(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>), _amount);
        <span class="hljs-keyword">emit</span> Withdraw(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>, _pid, _amount);
    }
</code></pre><p>先更新了质押池收益，然后计算用户未获得的sushi收益，将这些收益转到用户账户，然后更新rewardDebt，最后把LPToken还给用户。</p>]]></content:encoded>
            <author>vatalikbuterin@newsletter.paragraph.com (jambestwick)</author>
        </item>
        <item>
            <title><![CDATA[测试SushiSwap里的MasterChef合约_jamebestwick的博客-CSDN博客]]></title>
            <link>https://paragraph.com/@vatalikbuterin/sushiswap-masterchef-jamebestwick-csdn</link>
            <guid>lHYbbWEA06vV6Yf3AR3D</guid>
            <pubDate>Mon, 07 Feb 2022 09:29:52 GMT</pubDate>
            <description><![CDATA[SushiSwap是一个去中心化的交易所，其代码是由Uniswap V2分叉而来，支持质押挖矿、闪电贷等功能，其中MasterChef合约，用于质押挖矿。下面，介绍MasterChef合约的测试方法。1、拉取Sushiswap工程git clone https://github.com/sushiswap/sushiswap.git 1 2、修改hardhat.config.js文件将hardhat.config.js复制一份，源文件重命名为hardhat.config00.js，然后，将hardhat.config.js内容修改如下： //hardhat.config.js/** * @type import('hardhat/config').HardhatUserConfig */ require("@nomiclabs/hardhat-waffle"); //选取ganache下的4个账户的私钥// const PRIVATE_KEY1 = “9066…4c7f”;// const PRIVATE_KEY2 = “0c933…8b9c”;// const PRIVATE_...]]></description>
            <content:encoded><![CDATA[<figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/f546d7b9810710e4fe84b43ec03d1d93a232411bfabb4a1b3d03936eb3afed8c.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/sushiswap/sushiswap">SushiSwap</a>是一个去中心化的交易所，其代码是由<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/Uniswap/v2-core">Uniswap V2</a>分叉而来，支持质押挖矿、闪电贷等功能，其中<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/sushiswap/sushiswap/blob/canary/contracts/MasterChef.sol">MasterChef合约</a>，用于质押挖矿。下面，介绍MasterChef合约的测试方法。</p><h2 id="h-1sushiswap" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">1、拉取Sushiswap工程</h2><pre data-type="codeBlock" text="git clone https://github.com/sushiswap/sushiswap.git

   
   
1
"><code>git <span class="hljs-built_in">clone</span> https://github.com/sushiswap/sushiswap.git

   
   
1
</code></pre><h2 id="h-2hardhatconfigjs" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">2、修改hardhat.config.js文件</h2><p>将hardhat.config.js复制一份，源文件重命名为hardhat.config00.js，然后，将hardhat.config.js内容修改如下：    //hardhat.config.js</p><pre data-type="codeBlock" text="/**
 * @type import(&apos;hardhat/config&apos;).HardhatUserConfig
 */
 require(&quot;@nomiclabs/hardhat-waffle&quot;);
"><code>/**
 * @<span class="hljs-built_in">type</span> import(<span class="hljs-string">'hardhat/config'</span>).HardhatUserConfig
 */
 <span class="hljs-built_in">require</span>(<span class="hljs-string">"@nomiclabs/hardhat-waffle"</span>);
</code></pre><p>//选取ganache下的4个账户的私钥// const PRIVATE_KEY1 = “9066…4c7f”;// const PRIVATE_KEY2 = “0c933…8b9c”;// const PRIVATE_KEY3 = “28ba…2c9d”;// const PRIVATE_KEY4 = “da9f…1808”;</p><p>module.exports = {solidity: “0.6.12”,networks: {</p><pre data-type="codeBlock" text="//  ganache: {
//    url: `http://127.0.0.1:9545`,
//    accounts: [`0x${PRIVATE_KEY1}`,`0x${PRIVATE_KEY2}`,`0x${PRIVATE_KEY3}`,`0x${PRIVATE_KEY4}`]
//  },
 // ropsten: {
 //   url: `https://eth-ropsten.alchemyapi.io/v2/${ALCHEMY_API_KEY}`,
 //   accounts: [`0x${ROPSTEN_PRIVATE_KEY}`]
 // },
 // rinkeby: {
 //   url: `https://eth-rinkeby.alchemyapi.io/v2/${ALCHEMY_API_KEY}`,
 //   accounts: [`0x${rinkeby_PRIVATE_KEY}`]
 // },
"><code>//  ganache: {
<span class="hljs-regexp">//</span>    url: <span class="hljs-string">`http://127.0.0.1:9545`</span>,
<span class="hljs-regexp">//</span>    accounts: [<span class="hljs-string">`0x${PRIVATE_KEY1}`</span>,<span class="hljs-string">`0x${PRIVATE_KEY2}`</span>,<span class="hljs-string">`0x${PRIVATE_KEY3}`</span>,<span class="hljs-string">`0x${PRIVATE_KEY4}`</span>]
//  },
 <span class="hljs-regexp">//</span> ropsten: {
 <span class="hljs-regexp">//</span>   url: <span class="hljs-string">`https://eth-ropsten.alchemyapi.io/v2/${ALCHEMY_API_KEY}`</span>,
 <span class="hljs-regexp">//</span>   accounts: [<span class="hljs-string">`0x${ROPSTEN_PRIVATE_KEY}`</span>]
 // },
 <span class="hljs-regexp">//</span> rinkeby: {
 <span class="hljs-regexp">//</span>   url: <span class="hljs-string">`https://eth-rinkeby.alchemyapi.io/v2/${ALCHEMY_API_KEY}`</span>,
 <span class="hljs-regexp">//</span>   accounts: [<span class="hljs-string">`0x${rinkeby_PRIVATE_KEY}`</span>]
 // },
</code></pre><h2 id="h-3" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">3、安装依赖包</h2><h3 id="h-31-yarnlock" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">3.1 修改yarn.lock</h3><p>修改yarn.lock的第3669行，改成如下，如图(1)所示：</p><pre data-type="codeBlock" text="dependencies:
    ethereumjs-abi &quot;0.6.8&quot;

 
 
12
"><code>dependencies:
    ethereumjs<span class="hljs-operator">-</span><span class="hljs-built_in">abi</span> <span class="hljs-string">"0.6.8"</span>

 
 
<span class="hljs-number">12</span>
</code></pre><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/28243f3fca3f97bd7c84ab2bf4e990f4f6d1318b367bf48e9c664e2cb25ac7f5.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>图(1) 在yarn.lock的dependencies字段，指定ethereumjs-abi的版本号</p><h3 id="h-32-yarn" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">3.2 yarn安装依赖包</h3><pre data-type="codeBlock" text="sudo yarn install

 
 
1
"><code></code></pre><h2 id="h-4masterchef" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">4、测试MasterChef合约</h2><h3 id="h-41-hardhat" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">4.1 启动hardhat本地测试网节点</h3><p>启动hardhat的测试网节点，命令如下:</p><pre data-type="codeBlock" text="npx hardhat node

 
 
1
"><code></code></pre><p>它默认有20个账户，每个账户有10000ETH，如图(2)所示：</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/58e80ad552d1374ab5238c0198cd51e6a8d1f9a493100f2b554a5b759c77ff59.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>图(2) 启动hardhat本地的测试节点</p><h3 id="h-42" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">4.2 编译工程</h3><pre data-type="codeBlock" text="npx hardhat compile

 
 
1
"><code>npx hardhat <span class="hljs-built_in">compile</span>

 
 
<span class="hljs-number">1</span>
</code></pre><h3 id="h-43" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">4.3 测试合约</h3><p>a) 测试MasterChef合约</p><pre data-type="codeBlock" text="npx hardhat test test/MasterChef.test.ts

 
 
1
"><code>npx hardhat test test<span class="hljs-operator">/</span>MasterChef.test.ts

 
 
<span class="hljs-number">1</span>
</code></pre><p>效果如下:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/b732478b280e64c00494b62a47459625267a197dd92ece1611bd212e264c6015.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>图(3) 使用npx测试MasterChef合约</p><p>如图(3)所示，8个案例，全部测试通过。</p><p>b) 测试全部合约</p><pre data-type="codeBlock" text="npx hardhat test --verbose

 
 
1
"><code>npx hardhat test <span class="hljs-operator">-</span><span class="hljs-operator">-</span>verbose

 
 
<span class="hljs-number">1</span>
</code></pre><p>转载自：<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://blog.csdn.net/sanqima/article/details/120721209">https://blog.csdn.net/sanqima/article/details/120721209</a></p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/7fcbc269f2bd467d431ba9f3cdfbc79e226e096410be67dea4a8319884c0b44a.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/7fcbc269f2bd467d431ba9f3cdfbc79e226e096410be67dea4a8319884c0b44a.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/7fcbc269f2bd467d431ba9f3cdfbc79e226e096410be67dea4a8319884c0b44a.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/7fcbc269f2bd467d431ba9f3cdfbc79e226e096410be67dea4a8319884c0b44a.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/7fcbc269f2bd467d431ba9f3cdfbc79e226e096410be67dea4a8319884c0b44a.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://download.csdn.net/download/weixin_38685600/15746006">您将在每个新选项卡中打开一个精美的高清图像！ 惊人的！ 你是一个美食家吗？ 还是想当厨师的大师？ 在每个新标签页中，您都会获得令人敬畏的高质量<em>Masterchef</em> Food图像。 您会得到很大的启发，并且会喜欢这个不错的扩展。 简单易用（只需向下滚动即可查看更酷的照片或打开新标签）。 也可以离线工作。 超级快。 而已。 :)有关控制怪胎的详细信息：*代码中的所有内容都是100％透明的。 -在此处检查：https://github.com/h<em>app</em>yhey/<em>Masterchef</em>-food *无需任何怪异的权利。 *没有间谍软件或其他古怪的东西。 如果您喜欢，请给我一个不错的5星级评论。 谢谢。 对于其他程序员，我们将不胜感激。 您可以在此处找到完整的代码：https://github.com/h<em>app</em>yhey/<em>Masterchef</em>-food谢谢。 支持语言:Bahasa Indonesia,Bahasa Melayu,Deuts<em>ch</em>,Engli<em>sh</em>,Filipino,Français,Ki<em>swa</em>hili,Ned<em>er</em>lands,Norsk,Tiếng Việt,Türkçe,català,<em>da</em>nsk,ee<em>st</em>i,español,español (Latinoam&amp;eacu<em>te</em>;rica),hrvatski,italiano,latviešu,lietuvių,<em>ma</em>gyar,polski,portugu&amp;eci<em>rc</em>;s (Brasil),portugu&amp;eci<em>rc</em>;s (Portugal),rom&amp;aci<em>rc</em>;nă,slovensk&amp;yacu<em>te</em>;,slovenščina,<em>su</em>omi,svenska,Ε&amp;lamb<em>da</em>;&amp;lamb<em>da</em>;ηνι&amp;k<em>app</em>a;ά,Српски,български,русский,українська,עברית,فارسی‎,मराठी,हिन्दी,বাংলা,ગુજરાતી,தமிழ்,తెలుగు,ಕನ್ನಡ,മലയാളം,ไทย,‫العربية,中文 (简体),中文 (繁體),日本語,한국어</a></p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/7fcbc269f2bd467d431ba9f3cdfbc79e226e096410be67dea4a8319884c0b44a.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>©️2022 CSDN 皮肤主题：1024 设计师：我叫白小胖 <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://blog.csdn.net/">返回首页</a></p>]]></content:encoded>
            <author>vatalikbuterin@newsletter.paragraph.com (jambestwick)</author>
        </item>
        <item>
            <title><![CDATA[jambestwick - Overview]]></title>
            <link>https://paragraph.com/@vatalikbuterin/jambestwick-overview</link>
            <guid>zCfW2cbwOZ7IeYs8i2a3</guid>
            <pubDate>Mon, 07 Feb 2022 09:22:25 GMT</pubDate>
            <description><![CDATA[🚜🚙🚘🚗🚗🚕🚖🚛🚌🚍🚓🚔🚒🚑🚐🚚 HappyNewYear 2022One day in the cryptocurrency circle, one year in the worldAbout Me:I&apos;m senior Full-Stack Enigneer,use Android/Vue/Springboot... ...Co-Founder China Electronic the collection(ETC) , App Team Leader of RoadParkColar&apos;s father, dogecoin holder, block-chain developer part time.💰💰💰 BTC ETH SOLTwitter: jambestwick🚀 Quick start (Gatsby Cloud)Deploy this starter with one click on Gatsby Cloud:Pinned Documentation and issues of https://ji...]]></description>
            <content:encoded><![CDATA[<br><h2 id="h-happynewyear-2022" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">🚜🚙🚘🚗🚗🚕🚖🚛🚌🚍🚓🚔🚒🚑🚐🚚 HappyNewYear 2022</h2><h3 id="h-one-day-in-the-cryptocurrency-circle-one-year-in-the-world" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">One day in the cryptocurrency circle, one year in the world</h3><h3 id="h-about-me" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">About Me:</h3><ul><li><p>I&apos;m senior Full-Stack Enigneer,use Android/Vue/Springboot... ...</p></li><li><p>Co-Founder China Electronic the collection(ETC) , App Team Leader of RoadPark</p></li><li><p>Colar&apos;s father, dogecoin holder, block-chain developer part time.</p></li><li><p><strong>💰💰💰 BTC ETH SOL</strong></p></li></ul><h3 id="h-twitter-jambestwick" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Twitter: jambestwick</h3><h3 id="h-" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0"></h3><h3 id="h-quick-start-gatsby-cloud" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">🚀 Quick start (Gatsby Cloud)</h3><p>Deploy this starter with one click on <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.gatsbyjs.com/cloud/">Gatsby Cloud</a>:</p><h2 id="h-pinned" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Pinned</h2><ol><li><br></li><li><p>Documentation and issues of https://jitpack.io</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/jitpack/jitpack.io/stargazers">2.2k </a><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/jitpack/jitpack.io/network/members">169</a></p></li><li><p>Reference mobile app for BrightID</p><p>TypeScript <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/BrightID/BrightID/stargazers">154 </a><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/BrightID/BrightID/network/members">40</a></p></li><li><p>Off-chain gasless multi-governance client. Join us on Discord https://discord.gg/snapshot</p><p>Vue <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/snapshot-labs/snapshot/stargazers">454 </a><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/snapshot-labs/snapshot/network/members">425</a></p></li><li><p>功能强大的web3j以太坊用例，支持批量生成钱包，批量不同账户转账，查询余额等，监控，定时任务，交易mint等方法，持续更新中... ...</p><p>Java <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/jambestwick/web3jdemo/stargazers">160 </a><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/jambestwick/web3jdemo/network/members">37</a></p></li><li><p>Emergencywithdraw widget to be integrated on rugdoc.io</p><p>JavaScript <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/rugdocio/emergencywithdraw/stargazers">2 </a><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/rugdocio/emergencywithdraw/network/members">1</a></p></li></ol>]]></content:encoded>
            <author>vatalikbuterin@newsletter.paragraph.com (jambestwick)</author>
        </item>
    </channel>
</rss>